思维草图
为什么要使用集群
- 单台redis内存容量的限制
- 单台redis并发写量太大有性能瓶颈
redis集群认识
redis集群是对redis的水平扩容,即启动N个redis节点,将整个数据分布存储在这个N个节点中,每个节点存储总数据的1/N。
如下图:由3台master和3台slave组成的redis集群,每台master承接客户端三分之一请求和写入的数据,当master挂掉后,slave会自动替代master,做到高可用。
配置示例
在一台机器上,用不同的端口进行服务模拟
创建测试目录 redis-cluster,并将默认的redis.conf移动到该目录下
创建master1的配置文件:redis-6379.conf
include /Users/lihui/Documents/dev-tool/redis-cluster/redis.conf
daemonize yes
bind 127.0.0.1
dir /Users/lihui/Documents/dev-tool/redis-cluster/
port 6379
dbfilename dump_6379.rdb
pidfile /Users/lihui/Documents/dev-tool/redis-cluster/var/run/redis_6379.pid
logfile "./6379.log"
# 开启集群设置
cluster-enabled yes
# 设置节点配置文件
cluster-config-file node-6379.conf
# 设置节点失联时间,超过该时间(毫秒),集群自动进行主从切换
cluster-node-timeout 15000
创建master2的配置文件:redis-6380.conf
include /Users/lihui/Documents/dev-tool/redis-cluster/redis.conf
daemonize yes
bind 127.0.0.1
dir /Users/lihui/Documents/dev-tool/redis-cluster/
port 6380
dbfilename dump_6380.rdb
pidfile /Users/lihui/Documents/dev-tool/redis-cluster/var/run/redis_6380.pid
logfile "./6380.log"
# 开启集群设置
cluster-enabled yes
# 设置节点配置文件
cluster-config-file node-6380.conf
# 设置节点失联时间,超过该时间(毫秒),集群自动进行主从切换
cluster-node-timeout 15000
创建master3的配置文件:redis-6381.conf
include /Users/lihui/Documents/dev-tool/redis-cluster/redis.conf
daemonize yes
bind 127.0.0.1
dir /Users/lihui/Documents/dev-tool/redis-cluster/
port 6381
dbfilename dump_6381.rdb
pidfile /Users/lihui/Documents/dev-tool/redis-cluster/var/run/redis_6381.pid
logfile "./6381.log"
# 开启集群设置
cluster-enabled yes
# 设置节点配置文件
cluster-config-file node-6381.conf
# 设置节点失联时间,超过该时间(毫秒),集群自动进行主从切换
cluster-node-timeout 15000
创建slave1的配置文件:redis-6389.conf
include /Users/lihui/Documents/dev-tool/redis-cluster/redis.conf
daemonize yes
bind 127.0.0.1
dir /Users/lihui/Documents/dev-tool/redis-cluster/
port 6389
dbfilename dump_6389.rdb
pidfile /Users/lihui/Documents/dev-tool/redis-cluster/var/run/redis_6389.pid
logfile "./6389.log"
# 开启集群设置
cluster-enabled yes
# 设置节点配置文件
cluster-config-file node-6389.conf
# 设置节点失联时间,超过该时间(毫秒),集群自动进行主从切换
cluster-node-timeout 15000
创建slave2的配置文件:redis-6390.conf
include /Users/lihui/Documents/dev-tool/redis-cluster/redis.conf
daemonize yes
bind 127.0.0.1
dir /Users/lihui/Documents/dev-tool/redis-cluster/
port 6390
dbfilename dump_6390.rdb
pidfile /Users/lihui/Documents/dev-tool/redis-cluster/var/run/redis_6390.pid
logfile "./6390.log"
# 开启集群设置
cluster-enabled yes
# 设置节点配置文件
cluster-config-file node-6390.conf
# 设置节点失联时间,超过该时间(毫秒),集群自动进行主从切换
cluster-node-timeout 15000
创建slave3的配置文件:redis-6391.conf
include /Users/lihui/Documents/dev-tool/redis-cluster/redis.conf
daemonize yes
bind 127.0.0.1
dir /Users/lihui/Documents/dev-tool/redis-cluster/
port 6391
dbfilename dump_6391.rdb
pidfile /Users/lihui/Documents/dev-tool/redis-cluster/var/run/redis_6391.pid
logfile "./6391.log"
# 开启集群设置
cluster-enabled yes
# 设置节点配置文件
cluster-config-file node-6391.conf
# 设置节点失联时间,超过该时间(毫秒),集群自动进行主从切换
cluster-node-timeout 15000
启动六个redis服务
redis-server /Users/lihui/Documents/dev-tool/redis-cluster/redis-6379.conf
redis-server /Users/lihui/Documents/dev-tool/redis-cluster/redis-6380.conf
redis-server /Users/lihui/Documents/dev-tool/redis-cluster/redis-6381.conf
redis-server /Users/lihui/Documents/dev-tool/redis-cluster/redis-6389.conf
redis-server /Users/lihui/Documents/dev-tool/redis-cluster/redis-6390.conf
redis-server /Users/lihui/Documents/dev-tool/redis-cluster/redis-6391.conf
启动之后
确保每一个node文件生成成功
将6个节点合成一个集群
redis-cli --cluster create --cluster-replicas 1
127.0.0.1:6379 127.0.0.1:6380 127.0.0.1:6381
127.0.0.1:6389 127.0.0.1:6390 127.0.0.1:6391
注意
- 合体的命令后面会跟上所有节点的ip:port列表,多个之间用空格隔开,注意ip不要写 127.0.0.1,要写真实ip (我看别的帖子上是这样写的,我自己用127好像可以,但是别学我)
- --cluster-replicas 1:表示采用最简单的方式配置集群,即每个master配1个slave,6个节点就形成了3主3从
连接集群节点,查看集群信息:cluster nodes
使用 redis-cli -c 命令连接集群中6个节点中任何一个节点都可以,注意和之前的连接参数有点不同 redis-cli 命令后面多了一个 -c 参数,表示采用集群的方式连接,连上以后,然后使用 cluster nodes 可以查看集群节点信息,如下
集群中的每个节点都会生成一个ID, 这个ID信息会被写到node-xxxx.conf文件中,节点的ip和端口可能会发生变化,但是节点的ID是不会变的,其他节点可以通过其他节点的ID来认识各个节点。
验证集群数据的读写操作
在 6379 上操作的,但是请求被转发到了6380这个节点去处理了。这里报错是因为之前配置没有写密码。
slots(槽)
- Redis集群内部划分了16384个slots(插槽),合并的时候,会将每个slots映射到一个master上面。
- 数据库中的每个key都属于16384个slots中的其中1个,当通过key读写数据的时候,redis需要先根据 key计算出key对应的slots,然后根据slots和master的映射关系找到对应的redis节点,key对应的数据就在这个节点上面。
- 集群中使用公式 CRC16(key)%16384 计算key属于哪个槽
故障恢复
如果主节点下线,从节点是否能够提升为主节点?
要等15秒,从节点就会自动变成主节点,如果后续之前的主节点恢复,和之前的主从复制一样,也是挂在新节点下,成为从节点。
SpringBoot整合redis集群
引入对应的maven
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
配置redis cluster信息
# 集群节点(host:port),多个之间用逗号隔开
spring.redis.cluster.nodes=ip:port,ip:port,ip:port,ip:port,ip:port,ip:port
# 连接超时时间(毫秒)
spring.redis.timeout=60000