在 Redis 主从架构中,Slave,Master 挂掉了,如何保证可用性,实现继续读写 Redis。
1 哨兵
Sentinel
哨兵是用于监控 Redis 集群中 Master 状态的工具,是 Redis 高可用解决方案,哨兵可以监视一个或者多个 Redis Master 服务,以及这些 Master 服务的所有 Slave 服务;当某个 Master 服务宕机后,会把这个 Master 下的某个 Slave 服务升级为 Master 来替代已宕机的 Master 继续工作。
1.1 配置哨兵
打开安装 Redis 时解压的文件夹,里面有一个 sentinel.conf
文件,将该文件移动到相应的安装 Redis 目录中。然后修改一下配置:
# 取消保护模式,当Redis暴露在公网中,启动保护模式后,需要添加允许节点白名单才能访问
protected-mode no
# 哨兵启动的端口
port 26379
# 哨兵启动后,在后台运行
daemonize yes
# 哨兵日志文件
logfile /usr/local/redis/sentinel/redis-sentinel.log
# 哨兵工作空间
dir /usr/local/redis/sentinel
# sentinel monitor <master-name> <ip> <redis-port> <quorum>
# 设置 Master 节点,<quorum> 是指只需 <quorum> 台哨兵认为 Master 宕机了,就触发替代故障转移操作,将从节点变成 Master
sentinel monitor seieiMaster 192.168.191.135 6379 2
# 密码
sentinel auth-pass seieiMaster 123456
# Master 多长时间段没响应,哨兵就认为其宕机
sentinel down-after-milliseconds seieiMaster 30000
# 故障转移操作结束后,其它节点需要与新的 Master 做一次数据同步。
# 此时同步时,可以并行同步操作的节点个数
sentinel parallel-syncs seieiMaster 1
# 故障转移的最大操作时间,如果超过该时间,就由另一个节点接替故障转移操作
sentinel failover-timeout seieiMaster 180000
注意需要在防火墙中开放对应的端口,如
26379
配置了哨兵模式,就无需在 Redis 的核心配置文件中设置 Replication
配置(除了 masterauth
属性),因为就算设置了 Replication
,当启动了哨兵模式后,核心配置文件对应的 Replication
配置都会被修改,一切以哨兵的配置文件为准。
测试的时候我设置了三台虚拟机 A、B、C,A 为 Master,其余为 Slave,这时使用 tail -f /usr/local/redis/sentinel/redis-sentinel.log
查看哨兵日志,然后关闭 A 的 Redis,此时就触发替代故障转移操作,然后 C 虚拟机的 Redis 就会变成 Master,B 虚拟机的 Redis 的 Master 就会修改成 C 虚拟机中的 Redis。再将 A 的 Redis 重启,发现 A 的角色变成了 Slave。
最后将所有的 Redis 重启,发现 C 依旧是 Master 角色,而其他虚拟机是 Slave 角色,打开对应的哨兵配置文件,发现它已经被修改了 sentinel monitor <master-name> <ip> <redis-port> <quorum>
这条配置信息。
注意,如果没有设置
masterauth
属性,上面会出现 原 Master 恢复后不同步的问题,即当虚拟机 A 的 Redis 重启成为 Slave 后,输入info replication
命令查看它的同步状态是不成功(master_link_status:down
),这是因为一开始 A 扮演的角色是 Master,并没有设置它的核心文件masterauth
属性,而哨兵故障转移操作的时候也无法为其修改masterauth
属性,从而导致它成为 Slave 时,无法连接到新 Master。
所以在配置哨兵模式时,需要在所有的 Redis 核心配置文件中配置masterauth
属性(统一所有的密码)
1.2 SpringBoot 整合哨兵模式
在 yml
文件中配置:
spring:
redis:
# 单主机模式
# host: 192.168.13.128
# port: 6379
# password: 123456
# database: 0 # 使用索引为0 的数据库
# 哨兵模式
database: 0
password: 123456
sentinel:
# 在哨兵配置文件中设定 Master 昵称
master: seieiMaster
# 所有哨兵对应的地址
nodes: 192.168.253.4:26379,192.168.253.5:26379,192.168.253.6:26379
2 Redis 集群
之前的一主二从、哨兵模式,它们其实也就是一种集群,只是限于读取方面,提高读的并发,毕竟在正常情况下,用户的读写操作比例是八二开。但单个 Master 容量有限,数据达到一定程度也会有瓶颈,这时候可以通过水平扩展为多个 master-slave
成为多主多从集群。
构建 Redis 集群,最经典的 Redis 集群配备是:3个节点作为 Master,此外每个 Master 都配置一个 Slave,即整个集群需要6个节点,称为 三主三从。
Redis 的集群模式其实集合 主从复制 和 哨兵 的功能,当某一台主节点挂掉后,其对应的从节点会接替它作为新的主节点。
当主节点和从节点都关闭之后,此后只打开从节点,该从节点不会变为主节点
在构建集群之前,需要先做一下行为:
- 将 Redis 关闭,将
rdb
等文件删除清空 - 开放
16379
端口 - 在核心配置文件配置好
masterauth
属性,删除replicaof
属性 - 关闭所有哨兵
在 Redis 的核心配置文件 redis.conf
配置:
# 开启集群模式
cluster-enabled yes
# 每个集群节点需要有一个配置文件,这个文件用于存储集群下的集群状态等信息包括其它节点的信息,这个文件由 Redis 维护,如果需要重新创建集群,就需要将这个文件删掉既可
cluster-config-file nodes-6379.conf
# 超过时间,超时则认为 Master 宕机,随后主备切换
cluster-node-timeout 5000
# 开启 AOF 持久化模式
appendonly yes
配置好之后,就可以重启 Redis,全部 Redis 重启之后,在任意一台服务器中输入以下命令开启集群模式:
redis-cli -a password --cluster create ip1:prot1 ip2:port2 ip3:port3 ip4:port4 ip5:port5 ip6:port6 --cluster-replicas 1
其中 --cluster-replicas 1
表示主节点与节点的比例是1,即一台主节点对应一台节点。如果建立集群成功之后,Redis 会自动分配三组主从节点组,输入以下命令可以查询到对应的集群信息:
redis-cli -a password --cluster check ip:port
输出信息如下,它会显示主从信息,数据槽信息:
192.168.253.5:6379 (790a8840...) -> 1 keys | 5462 slots | 1 slaves.
192.168.253.4:6379 (060bdeb5...) -> 1 keys | 5461 slots | 1 slaves.
192.168.253.6:6379 (2b07958f...) -> 0 keys | 5461 slots | 1 slaves.
[OK] 2 keys in 3 masters.
0.00 keys per slot on average.
>>> Performing Cluster Check (using node 192.168.253.5:6379)
M: 790a884008f87aa988b1a6f1ed97c3152915b1a9 192.168.253.5:6379
slots:[5461-10922] (5462 slots) master
1 additional replica(s)
S: ca0d95ea1dbe587fdd6ac52c2360315f36844d6b 192.168.253.10:6379
slots: (0 slots) slave
replicates 790a884008f87aa988b1a6f1ed97c3152915b1a9
S: c12e80359b13d74a1640cc5dbd69e1edaa9af37d 192.168.253.8:6379
slots: (0 slots) slave
replicates 060bdeb5de3025feaf75188ce26060c789fdbf6a
M: 060bdeb5de3025feaf75188ce26060c789fdbf6a 192.168.253.4:6379
slots:[0-5460] (5461 slots) master
1 additional replica(s)
S: 3f0b3618d963449b5389c0ccb942747a958de636 192.168.253.7:6379
slots: (0 slots) slave
replicates 2b07958f4f523442d2beffd6a41a5b9ddd42f18c
M: 2b07958f4f523442d2beffd6a41a5b9ddd42f18c 192.168.253.6:6379
slots:[10923-16383] (5461 slots) master
1 additional replica(s)
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
最后使用以下命令进入到 Redis 客户端的集群模式:
redis-cli -a password -c [-h host -p port]
进入集群模式客户端后,可以使用以下命令获取信息
-
cluster info
:查看集群的信息,获取集群运作是否正常,槽节点的总数,正常运行的槽节点总数,不正常运行的槽节点总数,主从的对数等相关信息 -
cluster nodes
:查看各个节点信息
2.1 slot 槽节点
上面输入 --cluster check
命令和启动集群时都会出现 slot
槽节点这个概念,它其实就是用于存储数据的,只有主节点才有,从节点没有。如上面 --cluster check
输出的信息显示,一个三主三从的集群模式,一共会有 16384
个槽节点,它们会平均分配给各个主节点,如 192.168.253.4
分配了 0-5460
总共 5461
个槽节点,192.168.253.5
分配了 5461-10922
总共 5462
个槽节点,192.168.253.6
分配了 10923-16383
总共 5461
个槽节点。
它存储的方式是:根据设置数据的 Key 值进行一次一致性哈希求值,然后对这个哈希值进行 16384
求模,获取到的数值对应索引就会存储到相应的槽节点中。在使用 Redis 客户端进行 set
、get
操作的时候,就可能会出现 Master 的切换转移从而获取对应的数据,不过使用 keys *
这样的命令就不会出现 Master 的切换转移,相应的只会获取当前对应 Master 的所有 Key 值。
2.3 SpringBoot 整合集群
spring:
redis:
# 集群模式
password: 123456
cluster:
# 所有 Redis 地址及端口
nodes: 192.168.253.4:6379,192.168.253.5:6379,192.168.253.6:6379,192.168.253.7:6379,192.168.253.8:6379,192.168.253.10:6379