搭建Redis哨兵集群并使用RedisTemplate实现读写分离
一、理论相关
-
通过上篇博客:搭建Redis“主-从-从”模式集群并使用 RedisTemplate 实现读写分离,我们已经搭建好了Redis“主-从-从”模式集群并且实现读写分离,这里会出现几个问题:如果主库宕机了,我们就需要运行一个新主库,比如说把一个从库切换为主库,把它当成主库。这就会涉及到三个问题:
- 主库真的挂了吗?
- 该选择哪个从库作为主库?
- 怎么把新主库的相关信息通知给从库和客户端呢?
-
由此,我们便引出哨兵机制:
1、哨兵机制:主库挂了,如何不间断服务?
1.1、哨兵机制的基本流程
一个运行在特殊模式下的Redis进程,主从库实例运行的同时,它也在运行。主要负责三个任务:
-
监控 - 需要判断主库是否处于下线状态
- 哨兵进程在运行时,周期性地给所有的主从库发送PING命令,检测它们是否仍在线运行
- 从库没有在规定时间内响应哨兵的PING命令(对PING命令响应超时),标记为“下线状态”
- 主库对PING命令响应超时,判定主库下线,开始自动切换主库的流程
-
选主(选择主库) - 决定哪个从库实例作为主库
- 主库挂了以后,从很多个从库里,按照一定的规则选择一个从库实例,把它作为新的主库
-
通知
- 把新主库的连接信息发给其它从库,执行
replicaof
命令,和新主库建立连接,并进行数据复制 - 把新主库的连接信息通知给客户端,让它们把请求操作发到新主库
- 把新主库的连接信息发给其它从库,执行
1.2、主观下线和客观下线
主库:特别注意哨兵误判的情况 - 主库实际没有下线,哨兵误以为下线了
- 一般发生在集群网络压力较大、网络拥塞,或主库本身压力较大的情况
- 避免后续没有价值的开销
解决方法:
- 多实例组成的集群模式进行部署 - 哨兵集群
- 引入多个哨兵实例一起判断,降低误判率
- 只有大多数哨兵实例都判断主库已经“主观下线”,主库才会被标记为“客观下线”
- 当有 N 个哨兵实例时,最好要有 N/2 + 1 个实例判断主库为“主观下线”,才能最终判定主库为“客观下线”
- 有多少个实例做出“主观下线”的判断才可以 - 可以由 Redis 管理员自行设定
1.3、如何选定新主库?
-
筛选 + 打分
- 在多个从库中,先按照一定的筛选条件,把不符合条件的从库去掉
- 再按照一定的规则,给剩下的从库逐个打分,将得分最高的从库选为新主库
-
筛选条件
- 在线状态
- 网络连接状态
- 配置项down-after-milliseconds * 10
- down-after-milliseconds:认定主从库断连的最大连接超时时间
- 如果在 down-after-milliseconds 毫秒内,主从节点都没有通过网络联系上,就可以认为主从节点断连了
- 发生断连的次数超过10次,这个从库的网络状况不好,不适合作为新主库
-
打分(在某一轮中,从库得分最高,它就是主库,选主过程结束;否则进行下一轮打分)
- 从库优先级(优先级最高的从库得分高)
- 配置项slave-priority,给不同从库设置不同优先级
- 比如:两个从库中内存大的实例设置高优先级
- 从库复制进度(和旧主库同步程度最接近的从库得分高)
- 如果选择和旧主库同步最接近的那个从库作为主库,这个新主库上就会有最新的数据
- slave_repl_offset最接近master_repl_offset
- 从库ID号(ID号小的从库得分高)
- 默认规定
1.4、小结
-
组成哨兵机制可以解决主库之间切换服务的问题,但同样的,引入哨兵机制就相当于再引入实例,那么我们又会面临一些问题:
- 哨兵集群中有实例挂了,怎么办,会影响主库状态判断和选主吗?
- 哨兵集群多数实例达成共识,判断出主库“客观下线”后,由哪个实例来执行主从切换呢?
-
那么接下来,我们就引出哨兵集群的概念:
2、哨兵集群:哨兵挂了,主从库还能切换吗?
- 一旦多个实例组成了哨兵集群,即使有哨兵实例出现故障挂掉了,其他哨兵还能继续协作完成主从库切换的工作,包括判定主库是不是处于下线状态,选择新主库,以及通知从库和客户端。
2.1、基于pub/sub机制的哨兵集群组成
- 同时,它也可以从主库上订阅消息,获得其他哨兵发布的连接信息
- 除了哨兵实例,我们自己编写的应用程序也可以通过 Redis 进行消息的发布和订阅
频道:消息的类别
- 哨兵除了彼此间建立连接形成集群,还需要和从库建立连接
- 在哨兵的监控任务中,需要对主从库都进行心跳判断,而且在主从库切换完成后,需要通知从库,让它们和新主库同步
- 主从库切换后,客户端也需要知道新主库的连接信息,才能向新主库发送请求操作
- 哨兵还需要把新主库的信息告诉客户端
- 客户端需要获取到哨兵集群在监控、选主、切换这个过程中发生的各种事件
2.2、基于pub/sub机制的客户端事件通知
- 从本质上说,哨兵就是一个运行在特定模式下的 Redis 实例,只不过它并不服务请求操作,只是完成监控、选主和通知的任务。
- 每个哨兵实例也提供pub/sub机制
操作步骤:
- 客户端读取哨兵的配置文件
- 获得哨兵的地址和端口,和哨兵建立网络连接
- 在客户端执行订阅命令,获取不同的事件消息
SUBSCRIBE +odown
PSUBSRCIBE *
switch-master <master name> <oldip> <oldport> <newip> <newport>
- 表示主库已经切换,新主库的IP地址和端口信息已经有了
- 客户端不仅可以在主从切换后得到新主库的连接信息,还可以监控到主从库切换过程中发生的各个重要事件
- 客户端就可以知道主从切换进行到哪一步,有助于了解切换进度
2.3、由哪个哨兵执行主从切换?
- “投票仲裁”过程
在投票过程中,任何一个想成为 Leader 的哨兵,要满足两个条件:
- 拿到半数以上的赞成票
- 拿到的票数同时还需要大于等于哨兵配置文件中的 quorum 值
3个哨兵、quorum为2的选举过程:
时间 | 哨兵1(S1) | 哨兵2(S2) | 哨兵3(S3) |
---|---|---|---|
T1 | 判断主库为“客观下线”,给自己投1票Y,向S2、S3发投票请求,表示要成为Leader | ||
T2 | 判断主库为“客观下线”,给自己投1票Y,向S1、S3发投票请求,表示要成为Leader | ||
T3 | 收到S3的请求,回复N(已经给自己投了一票Y,不能再给其它哨兵投Y) | 收到S3的请求,回复Y | |
T4 | 收到S1的请求,回复N(网络传输可能拥塞了,导致投票请求传输慢了) | ||
T5 | 1票Y,1票N | 2票Y,成为Leader |
- 如果S3没有拿到2票Y,这轮投票就不会产生Leader,哨兵集群会等待一段时间(也就是哨兵故障转移超时时间的 2 倍),再重新选举。
- 如果哨兵集群只有 2 个实例,此时,一个哨兵要想成为 Leader,必须获得 2 票,而不是 1 票。所以,如果有个哨兵挂掉了,那么,此时的集群是无法进行主从库切换的。因此,通常我们至少会配置 3 个哨兵实例。
2.4、小结
哨兵集群的关键机制:
- 基于 pub/sub 机制的哨兵集群组成过程;
- 基于 INFO 命令的从库列表,这可以帮助哨兵和从库建立连接;
- 基于哨兵自身的 pub/sub 功能,这实现了客户端和哨兵之间的事件通知。
- 要保证所有哨兵实例的配置是一致的,尤其是主观下线的判断值 down-after-milliseconds。
- 可能会因为这个值在不同的哨兵实例上配置不一致,导致哨兵集群一直没有对有故障的主库形成共识,也就没有及时切换主库,最终的结果就是集群服务不稳定。
二、实践
运行环境:虚拟机操作系统:centOS7,IP地址:192.168.88.130
centOS 环境下已经安装好了 docker 和 docker-compose
Windows 环境下已经安装好了 redis-cli.exe 工具(用来查看哨兵集群状态)
采用Redis:7.4.0
在上一篇博文中,我们搭建了Redis主从库集群,结构如下:
[root@centos redis-cluster]# find . -print | sed -e 's;[^/]*/;|____;g;s;____|; |;g'
.
|____docker-compose.yml
|____redis0
| |____data
| | |____dump.rdb
| |____redis.conf
|____redis1
| |____data
| | |____dump.rdb
| |____redis.conf
|____redis2
| |____data
| | |____dump.rdb
| |____redis.conf
|____redis3
| |____data
| | |____dump.rdb
| |____redis.conf
|____redis4
| |____data
| | |____dump.rdb
| |____redis.conf
-
其中,
redis0
为主库,redis1
、redis2
分别为从库I、从库II;redis3
、redis4
分别为从库II的从库1和从库2 -
接下来,我们在该结构的基础上,搭建
sentinel
哨兵集群
-
首先,我们先看看上一次搭建集群的
redis.conf
:redis0/redis.conf
protected-mode no bind 0.0.0.0 save 900 1 save 300 10 save 60 10000 rdbcompression yes dbfilename dump.rdb dir /data # 关闭 aof 日志备份 appendonly no # 自定义密码 requirepass root # 启动端口 port 6379 # 换成自己的虚拟机的IP replica-announce-ip 192.168.88.130
redis1/redis.conf
protected-mode no bind 0.0.0.0 save 900 1 save 300 10 save 60 10000 rdbcompression yes dbfilename dump.rdb dir /data # 关闭 aof 日志备份 appendonly no # 启动端口 port 6479 # 将当前 redis 作为 redis0 的 slave # 由于 docker 使用 host 模式,使用的是宿主机的 ip replicaof 192.168.88.130 6379 # 自定义密码 requirepass root # 访问 master 节点时需要提供的密码 masterauth root masteruser redis0 replica-announce-ip 192.168.88.130
redis2/redis.conf
protected-mode no bind 0.0.0.0 save 900 1 save 300 10 save 60 10000 rdbcompression yes dbfilename dump.rdb dir /data # 关闭 aof 日志备份 appendonly no # 启动端口 port 6579 # 将当前 redis 作为 redis0 的 slave # 由于 docker 使用 host 模式,使用的是宿主机的 ip replicaof 192.168.88.130 6379 # 自定义密码 requirepass root # 访问 master 节点时需要提供的密码 masterauth root replica-announce-ip 192.168.88.130
redis3/redis.conf
protected-mode no bind 0.0.0.0 save 900 1 save 300 10 save 60 10000 rdbcompression yes dbfilename dump.rdb dir /data # 关闭 aof 日志备份 appendonly no # 启动端口 port 6679 # 将当前 redis 作为 redis2 的 slave # 由于 docker 使用 host 模式,使用的是宿主机的 ip replicaof 192.168.88.130 6579 # 自定义密码 requirepass root # 访问 master 节点时需要提供的密码 masterauth root replica-announce-ip 192.168.88.130
redis4/redis.conf
protected-mode no bind 0.0.0.0 save 900 1 save 300 10 save 60 10000 rdbcompression yes dbfilename dump.rdb dir /data # 关闭 aof 日志备份 appendonly no # 启动端口 port 6779 # 将当前 redis 作为 redis2 的 slave # 由于 docker 使用 host 模式,使用的是宿主机的 ip replicaof 192.168.88.130 6579 # 自定义密码 requirepass root # 访问 master 节点时需要提供的密码 masterauth root replica-announce-ip 192.168.88.130
1、搭建sentinel
- 新建目录
[root@centos redis-cluster]# mkdir sentinel1
[root@centos redis-cluster]# mkdir sentinel2
[root@centos redis-cluster]# mkdir sentinel3
[root@centos redis-cluster]# mkdir sentinel1/data
[root@centos redis-cluster]# mkdir sentinel2/data
[root@centos redis-cluster]# mkdir sentinel3/data
- 编辑
sentinel.conf
[root@centos redis-cluster]# vi sentinel1/sentinel.conf
port 26379
protected-mode no
# 虚拟机会有多个 ip,这里指定具体一个 ip 地址
sentinel announce-ip 192.168.88.130
# 配置监控的集群主节点的 ip 和 端口
# 如果有 2 个 sentinel 节点认为主节点主观下线,
# 则主节点就被认为是客观下线
# redis 的集群名称可以随意配置,这里配置为 jobs
sentinel monitor jobs 192.168.88.130 6379 2
# sentinel 会向集群中的节点定期发送心跳检测命令,
# 如果在配置时间(毫秒)内没有响应回复,则被认为是主观下线
sentinel down-after-milliseconds jobs 5000
# 主备切换时,最多有多少个 slave 同时对新的 master 进行同步
sentinel parallel-syncs jobs 2
# 故障转移的超时时间
sentinel failover-timeout jobs 60000
# 如果在 Redis 设置了密码,这里就需要提供访问密码
sentinel auth-pass jobs root
# 这里设置访问 sentinel 的密码
requirepass root
# 数据存储目录
dir /data
[root@centos redis-cluster]# vi sentinel2/sentinel.conf
port 26479
protected-mode no
# 虚拟机会有多个 ip,这里指定具体一个 ip 地址
sentinel announce-ip 192.168.88.130
# 配置监控的集群主节点的 ip 和 端口
# 如果有 2 个 sentinel 节点认为主节点主观下线,
# 则主节点就被认为是客观下线
# redis 的集群名称可以随意配置,这里配置为 jobs
sentinel monitor jobs 192.168.88.130 6379 2
# sentinel 会向集群中的节点定期发送心跳检测命令,
# 如果在配置时间(毫秒)内没有响应回复,则被认为是主观下线
sentinel down-after-milliseconds jobs 5000
# 主备切换时,最多有多少个 slave 同时对新的 master 进行同步
sentinel parallel-syncs jobs 2
# 故障转移的超时时间
sentinel failover-timeout jobs 60000
# 如果在 Redis 设置了密码,这里就需要提供访问密码
sentinel auth-pass jobs root
# 这里设置访问 sentinel 的密码
requirepass root
# 数据存储目录
dir /data
[root@centos redis-cluster]# vi sentinel3/sentinel.conf
port 26579
protected-mode no
# 虚拟机会有多个 ip,这里指定具体一个 ip 地址
sentinel announce-ip 192.168.88.130
# 配置监控的集群主节点的 ip 和 端口
# 如果有 2 个 sentinel 节点认为主节点主观下线,
# 则主节点就被认为是客观下线
# redis 的集群名称可以随意配置,这里配置为 jobs
sentinel monitor jobs 192.168.88.130 6379 2
# sentinel 会向集群中的节点定期发送心跳检测命令,
# 如果在配置时间(毫秒)内没有响应回复,则被认为是主观下线
sentinel down-after-milliseconds jobs 5000
# 主备切换时,最多有多少个 slave 同时对新的 master 进行同步
sentinel parallel-syncs jobs 2
# 故障转移的超时时间
sentinel failover-timeout jobs 60000
# 如果在 Redis 设置了密码,这里就需要提供访问密码
sentinel auth-pass jobs root
# 这里设置访问 sentinel 的密码
requirepass root
# 数据存储目录
dir /data
- 然后,我们在
docker-compose.yml
添加sentinel
的配置项
[root@centos redis-cluster]# vi docker-compose.yml
services:
redis0:
image: redis
container_name: redis0
restart: always
privileged: true
network_mode: "host"
volumes:
- /root/docker/redis-cluster/redis0/data:/data
- /root/docker/redis-cluster/redis0/redis.conf:/etc/redis.conf
command:
redis-server /etc/redis.conf
redis1:
image: redis
container_name: redis1
restart: always
privileged: true
network_mode: "host"
volumes:
- /root/docker/redis-cluster/redis1/data:/data
- /root/docker/redis-cluster/redis1/redis.conf:/etc/redis.conf
command:
redis-server /etc/redis.conf
depends_on:
- redis0
redis2:
image: redis
container_name: redis2
restart: always
privileged: true
network_mode: "host"
volumes:
- /root/docker/redis-cluster/redis2/data:/data
- /root/docker/redis-cluster/redis2/redis.conf:/etc/redis.conf
command:
redis-server /etc/redis.conf
depends_on:
- redis0
redis3:
image: redis
container_name: redis3
restart: always
privileged: true
network_mode: "host"
volumes:
- /root/docker/redis-cluster/redis3/data:/data
- /root/docker/redis-cluster/redis3/redis.conf:/etc/redis.conf
command:
redis-server /etc/redis.conf
depends_on:
- redis2
redis4:
image: redis
container_name: redis4
restart: always
privileged: true
network_mode: "host"
volumes:
- /root/docker/redis-cluster/redis4/data:/data
- /root/docker/redis-cluster/redis4/redis.conf:/etc/redis.conf
command:
redis-server /etc/redis.conf
depends_on:
- redis2
sentinel1:
image: redis
container_name: sentinel1
restart: always
privileged: true
network_mode: "host"
volumes:
- /root/docker/redis-cluster/sentinel1/sentinel.conf:/etc/sentinel.conf
command:
redis-sentinel /etc/sentinel.conf
depends_on:
- redis0
sentinel2:
image: redis
container_name: sentinel2
restart: always
privileged: true
network_mode: "host"
volumes:
- /root/docker/redis-cluster/sentinel2/sentinel.conf:/etc/sentinel.conf
command:
redis-sentinel /etc/sentinel.conf
depends_on:
- redis0
sentinel3:
image: redis
container_name: sentinel3
restart: always
privileged: true
network_mode: "host"
volumes:
- /root/docker/redis-cluster/sentinel3/sentinel.conf:/etc/sentinel.conf
command:
redis-sentinel /etc/sentinel.conf
depends_on:
- redis0
- 最后,我们在
docker-compose.yml
所在目录运行docker-compose up -d
命令启动服务
[root@centos redis-cluster]# docker-compose up -d
[+] Running 8/8
✔ Container redis0 Running 0.0s
✔ Container redis2 Running 0.0s
✔ Container redis4 Running 0.0s
✔ Container sentinel1 Started 0.4s
✔ Container sentinel2 Started 0.4s
✔ Container sentinel3 Started 0.2s
✔ Container redis1 Running 0.0s
✔ Container redis3 Running
- 还可以通过
docker-compose ps
查看集群运行状态
[root@centos redis-cluster]# docker-compose ps
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
redis0 redis "docker-entrypoint.s…" redis0 4 days ago Up 41 minutes
redis1 redis "docker-entrypoint.s…" redis1 4 days ago Up 41 minutes
redis2 redis "docker-entrypoint.s…" redis2 4 days ago Up 41 minutes
redis3 redis "docker-entrypoint.s…" redis3 4 days ago Up 41 minutes
redis4 redis "docker-entrypoint.s…" redis4 4 days ago Up 41 minutes
sentinel1 redis "docker-entrypoint.s…" sentinel1 17 minutes ago Up 35 seconds
sentinel2 redis "docker-entrypoint.s…" sentinel2 17 minutes ago Up 17 minutes
sentinel3 redis "docker-entrypoint.s…" sentinel3 17 minutes ago Up 17 minutes
2、在Windows环境下查看虚拟机中搭建的哨兵状态
- 进入到 Redis 目录,在该目录下打开 cmd 命令行,运行
redis-cli.exe -h 192.168.88.130 -p 26379 -a root
- 查看master节点的信息
sentinel master [sentinel集群名称]
- 查看除自己之外,sentinel 集群中的其它 sentinel 节点信息
sentinel sentinels [sentinel集群名称]
- 查看slave节点的信息
sentinel slaves [sentinel集群名称]
- 注:哨兵不直接支持级联从节点的监控(即哨兵一般不会监控从节点的从节点 - 我们所搭建的redis3和redis4),最佳实践通常是避免级联结构,使用简单的“主从”模式,减少管理和故障切换的复杂性。
- 因此,我们搭建的redis集群如下:
3、模拟master节点宕机
- 我们将主库redis0停止再开机:
[root@centos redis-cluster]# docker-compose stop redis0
[+] Stopping 1/1
✔ Container redis0 Stopped 0.9s
[root@centos redis-cluster]# docker-compose start redis0
[+] Running 1/1
✔ Container redis0 Started
- 我们再在sentinel中查看主从信息,便会发现主库更新,原本的redis0主库更换为从库。
三、RedisTemplate
- 配置文件参考:
spring:
data:
redis:
# 这里只需配置主节点的信息即可
# RedisTemplate可以从主节点信息中获取从节点信息
host: 192.168.88.130
port: 6379
password: root
jedis:
pool:
# 最大连接数
max-active: 10
# 最大空闲连接数
max-idle: 5
# 最小空闲
min-idle: 1
# 连接超时时间(毫秒)
max-wait: 8000
sentinel:
password: root
master: jobs
nodes:
- 192.168.88.130:26379
- 192.168.88.130:26479
- 192.168.88.130:26579
个人问题记录:
-
在搭建sentinel时:
[root@centos redis-cluster]# docker-compose ps NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS redis0 redis "docker-entrypoint.s…" redis0 4 days ago Up 26 minutes redis1 redis "docker-entrypoint.s…" redis1 4 days ago Up 26 minutes redis2 redis "docker-entrypoint.s…" redis2 4 days ago Up 26 minutes redis3 redis "docker-entrypoint.s…" redis3 4 days ago Up 26 minutes redis4 redis "docker-entrypoint.s…" redis4 4 days ago Up 26 minutes sentinel1 redis "docker-entrypoint.s…" sentinel1 2 minutes ago Restarting (1) 20 seconds ago sentinel2 redis "docker-entrypoint.s…" sentinel2 2 minutes ago Up 2 minutes sentinel3 redis "docker-entrypoint.s…" sentinel3 2 minutes ago Up 2 minutes
- 查看命令发现
sentinel1
容器在启动后处于不断重启的状态,这通常表示该容器内的 Redis 哨兵服务遇到了错误并退出 - 于是查看日志:
[root@centos redis-cluster]# docker-compose logs sentinel1 sentinel1 | sentinel1 | *** FATAL CONFIG FILE ERROR (Redis 7.4.0) *** sentinel1 | Reading the configuration file, at line 2 sentinel1 | >>> 'rt 26379' sentinel1 | Bad directive or wrong number of arguments
- 发现
sentinel1
的配置文件在第 2 行存在语法问题。日志中提到的内容>>> 'rt 26379'
,发现是配置文件拼写的错误,修改配置文件即可。
- 查看命令发现
[root@centos redis-cluster]# docker-compose ps
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
redis0 redis "docker-entrypoint.s…" redis0 4 days ago Up 41 minutes
redis1 redis "docker-entrypoint.s…" redis1 4 days ago Up 41 minutes
redis2 redis "docker-entrypoint.s…" redis2 4 days ago Up 41 minutes
redis3 redis "docker-entrypoint.s…" redis3 4 days ago Up 41 minutes
redis4 redis "docker-entrypoint.s…" redis4 4 days ago Up 41 minutes
sentinel1 redis "docker-entrypoint.s…" sentinel1 17 minutes ago Up 35 seconds
sentinel2 redis "docker-entrypoint.s…" sentinel2 17 minutes ago Up 17 minutes
sentinel3 redis "docker-entrypoint.s…" sentinel3 17 minutes ago Up 17 minutes
- 在模拟master节点宕机时:
因为我一开始搭建的是“主从从”模式集群,再在该基础上搭建哨兵集群,结构如下:
哨兵不直接支持级联从节点的监控(即哨兵一般不会监控从节点的从节点 - 我们所搭建的redis3和redis4),但这时我们已经搭建好了,就不打算将redis3和redis4rm
,我们先将redis0 stop再start,然后发现:
当 Redis 哨兵检测到主节点
redis0
不可用时,它将redis2
切换为新的主节点。由于redis3
和redis4
原本是redis2
的从节点,这个链条并未断裂,且由于redis2
成为了主节点,哨兵将其下的所有从节点(包括原本的从节点的从节点)也作为它的从节点进行管理。
-
redis2
成为新的主节点后,redis1
、redis3
、和redis4
均会被识别为redis2
的直接从节点,形成多层次的直接复制。 -
因为哨兵在切换时没有自动重设
redis3
和redis4
的主从关系,它们仍然保持与redis2
的连接。 -
我们在RDM中对redis进行
info replication
,观察如下:
- 为什么没有
redis0
?redis0
作为redis2
的从节点重新连接时,可能还没有完成所有的复制同步和状态更新。即使redis0
成功连接为从节点,它的状态可能还在初始化过程中,导致暂时没有出现在redis2
的从节点列表中。当我们再次尝试稍等片刻,然后再次使用info replication
检查,就可以看到redis0
也成为了redis2
的slave
当我们对其中一个sentinel进行
sentinel slaves jobs
操作后,发现:
- 哨兵在切换后会将所有的下层节点(包括多级从节点)作为新的主节点的从节点进行管理。因此,当你在
sentinel slaves jobs
中查询时,能看到所有属于redis2
直接或间接从属关系的节点(即redis1
、redis3
、redis4
等),都被列为它的从节点。
因此,为了减少不必要的麻烦,我们会简化为一层“主-从”结构,以便哨兵更高效地管理复制关系。
参考博文:
Redis 哨兵集群搭建并使用 RedisTemplate 实现读写分离
参考书籍:
《Redis核心技术与实战》