搭建Redis哨兵集群并使用RedisTemplate实现读写分离

news/2024/10/10 12:21:55/文章来源:https://www.cnblogs.com/chuchenbanban/p/18456047

一、理论相关

  • 通过上篇博客:搭建Redis“主-从-从”模式集群并使用 RedisTemplate 实现读写分离,我们已经搭建好了Redis“主-从-从”模式集群并且实现读写分离,这里会出现几个问题:如果主库宕机了,我们就需要运行一个新主库,比如说把一个从库切换为主库,把它当成主库。这就会涉及到三个问题:

    1. 主库真的挂了吗?
    2. 该选择哪个从库作为主库?
    3. 怎么把新主库的相关信息通知给从库和客户端呢?
  • 由此,我们便引出哨兵机制

1、哨兵机制:主库挂了,如何不间断服务?

1.1、哨兵机制的基本流程

一个运行在特殊模式下的Redis进程,主从库实例运行的同时,它也在运行。主要负责三个任务:

  1. 监控 - 需要判断主库是否处于下线状态

    1. 哨兵进程在运行时,周期性地给所有的主从库发送PING命令,检测它们是否仍在线运行
    2. 从库没有在规定时间内响应哨兵的PING命令(对PING命令响应超时),标记为“下线状态”
    3. 主库对PING命令响应超时,判定主库下线,开始自动切换主库的流程
  2. 选主(选择主库) - 决定哪个从库实例作为主库

    1. 主库挂了以后,从很多个从库里,按照一定的规则选择一个从库实例,把它作为新的主库
  3. 通知

    1. 把新主库的连接信息发给其它从库,执行replicaof命令,和新主库建立连接,并进行数据复制
    2. 把新主库的连接信息通知给客户端,让它们把请求操作发到新主库

1.2、主观下线和客观下线

主库:特别注意哨兵误判的情况 - 主库实际没有下线,哨兵误以为下线了

  • 一般发生在集群网络压力较大、网络拥塞,或主库本身压力较大的情况
  • 避免后续没有价值的开销

解决方法:

  • 多实例组成的集群模式进行部署 - 哨兵集群
  • 引入多个哨兵实例一起判断,降低误判率
  • 只有大多数哨兵实例都判断主库已经“主观下线”,主库才会被标记为“客观下线”

image

  • 当有 N 个哨兵实例时,最好要有 N/2 + 1 个实例判断主库为“主观下线”,才能最终判定主库为“客观下线”
  • 有多少个实例做出“主观下线”的判断才可以 - 可以由 Redis 管理员自行设定

1.3、如何选定新主库?

  • 筛选 + 打分

    1. 在多个从库中,先按照一定的筛选条件,把不符合条件的从库去掉
    2. 再按照一定的规则,给剩下的从库逐个打分,将得分最高的从库选为新主库

image-20241009165754869

  • 筛选条件

    1. 在线状态
    2. 网络连接状态
      • 配置项down-after-milliseconds * 10
      • down-after-milliseconds:认定主从库断连的最大连接超时时间
      • 如果在 down-after-milliseconds 毫秒内,主从节点都没有通过网络联系上,就可以认为主从节点断连了
      • 发生断连的次数超过10次,这个从库的网络状况不好,不适合作为新主库
  • 打分(在某一轮中,从库得分最高,它就是主库,选主过程结束;否则进行下一轮打分)

    1. 从库优先级(优先级最高的从库得分高)
    • 配置项slave-priority,给不同从库设置不同优先级
    • 比如:两个从库中内存大的实例设置高优先级
    1. 从库复制进度(和旧主库同步程度最接近的从库得分高)
    • 如果选择和旧主库同步最接近的那个从库作为主库,这个新主库上就会有最新的数据
    • slave_repl_offset最接近master_repl_offset
    1. 从库ID号(ID号小的从库得分高)
    • 默认规定

1.4、小结

image

  • 组成哨兵机制可以解决主库之间切换服务的问题,但同样的,引入哨兵机制就相当于再引入实例,那么我们又会面临一些问题:

    1. 哨兵集群中有实例挂了,怎么办,会影响主库状态判断和选主吗?
    2. 哨兵集群多数实例达成共识,判断出主库“客观下线”后,由哪个实例来执行主从切换呢?
  • 那么接下来,我们就引出哨兵集群的概念:

2、哨兵集群:哨兵挂了,主从库还能切换吗?

  • 一旦多个实例组成了哨兵集群,即使有哨兵实例出现故障挂掉了,其他哨兵还能继续协作完成主从库切换的工作,包括判定主库是不是处于下线状态,选择新主库,以及通知从库和客户端。

2.1、基于pub/sub机制的哨兵集群组成

  • 同时,它也可以从主库上订阅消息,获得其他哨兵发布的连接信息
  • 除了哨兵实例,我们自己编写的应用程序也可以通过 Redis 进行消息的发布和订阅

频道:消息的类别

image

  • 哨兵除了彼此间建立连接形成集群,还需要和从库建立连接
  • 在哨兵的监控任务中,需要对主从库都进行心跳判断,而且在主从库切换完成后,需要通知从库,让它们和新主库同步

image

  • 主从库切换后,客户端也需要知道新主库的连接信息,才能向新主库发送请求操作
  • 哨兵还需要把新主库的信息告诉客户端
  • 客户端需要获取到哨兵集群在监控、选主、切换这个过程中发生的各种事件

2.2、基于pub/sub机制的客户端事件通知

  • 从本质上说,哨兵就是一个运行在特定模式下的 Redis 实例,只不过它并不服务请求操作,只是完成监控、选主和通知的任务。
  • 每个哨兵实例也提供pub/sub机制

image

操作步骤:

  1. 客户端读取哨兵的配置文件
  2. 获得哨兵的地址和端口,和哨兵建立网络连接
  3. 在客户端执行订阅命令,获取不同的事件消息
SUBSCRIBE +odown
PSUBSRCIBE *
switch-master <master name> <oldip> <oldport> <newip> <newport>
  • 表示主库已经切换,新主库的IP地址和端口信息已经有了
  • 客户端不仅可以在主从切换后得到新主库的连接信息,还可以监控到主从库切换过程中发生的各个重要事件
  • 客户端就可以知道主从切换进行到哪一步,有助于了解切换进度

2.3、由哪个哨兵执行主从切换?

  • “投票仲裁”过程

image

在投票过程中,任何一个想成为 Leader 的哨兵,要满足两个条件:

  1. 拿到半数以上的赞成票
  2. 拿到的票数同时还需要大于等于哨兵配置文件中的 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、小结

image

哨兵集群的关键机制

  1. 基于 pub/sub 机制的哨兵集群组成过程;
  2. 基于 INFO 命令的从库列表,这可以帮助哨兵和从库建立连接;
  3. 基于哨兵自身的 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为主库,redis1redis2分别为从库I、从库II;redis3redis4分别为从库II的从库1和从库2

  • 接下来,我们在该结构的基础上,搭建sentinel哨兵集群

  1. 首先,我们先看看上一次搭建集群的redis.conf

    • redis0/redis.conf
    protected-mode nobind 0.0.0.0save 900 1
    save 300 10
    save 60 10000rdbcompression yesdbfilename dump.rdbdir /data# 关闭 aof 日志备份
    appendonly no# 自定义密码
    requirepass root# 启动端口
    port 6379# 换成自己的虚拟机的IP
    replica-announce-ip 192.168.88.130
    
    • redis1/redis.conf
    protected-mode nobind 0.0.0.0save 900 1
    save 300 10
    save 60 10000rdbcompression yesdbfilename dump.rdbdir /data# 关闭 aof 日志备份
    appendonly no# 启动端口
    port 6479# 将当前 redis 作为 redis0 的 slave
    # 由于 docker 使用 host 模式,使用的是宿主机的 ip
    replicaof 192.168.88.130 6379# 自定义密码
    requirepass root# 访问 master 节点时需要提供的密码
    masterauth rootmasteruser redis0replica-announce-ip 192.168.88.130
    
    • redis2/redis.conf
    protected-mode nobind 0.0.0.0save 900 1
    save 300 10
    save 60 10000rdbcompression yesdbfilename dump.rdbdir /data# 关闭 aof 日志备份
    appendonly no# 启动端口
    port 6579# 将当前 redis 作为 redis0 的 slave
    # 由于 docker 使用 host 模式,使用的是宿主机的 ip
    replicaof 192.168.88.130 6379# 自定义密码
    requirepass root# 访问 master 节点时需要提供的密码
    masterauth rootreplica-announce-ip 192.168.88.130
    
    • redis3/redis.conf
    protected-mode nobind 0.0.0.0save 900 1
    save 300 10
    save 60 10000rdbcompression yesdbfilename dump.rdbdir /data# 关闭 aof 日志备份
    appendonly no# 启动端口
    port 6679# 将当前 redis 作为 redis2 的 slave
    # 由于 docker 使用 host 模式,使用的是宿主机的 ip
    replicaof 192.168.88.130 6579# 自定义密码
    requirepass root# 访问 master 节点时需要提供的密码
    masterauth rootreplica-announce-ip 192.168.88.130
    
    • redis4/redis.conf
    protected-mode nobind 0.0.0.0save 900 1
    save 300 10
    save 60 10000rdbcompression yesdbfilename dump.rdbdir /data# 关闭 aof 日志备份
    appendonly no# 启动端口
    port 6779# 将当前 redis 作为 redis2 的 slave
    # 由于 docker 使用 host 模式,使用的是宿主机的 ip
    replicaof 192.168.88.130 6579# 自定义密码
    requirepass root# 访问 master 节点时需要提供的密码
    masterauth rootreplica-announce-ip 192.168.88.130
    

1、搭建sentinel

  1. 新建目录
[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
  1. 编辑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
  1. 然后,我们在docker-compose.yml添加sentinel的配置项
[root@centos redis-cluster]# vi docker-compose.yml
services:redis0:image: rediscontainer_name: redis0restart: alwaysprivileged: truenetwork_mode: "host"volumes:- /root/docker/redis-cluster/redis0/data:/data- /root/docker/redis-cluster/redis0/redis.conf:/etc/redis.confcommand:redis-server /etc/redis.confredis1:image: rediscontainer_name: redis1restart: alwaysprivileged: truenetwork_mode: "host"volumes:- /root/docker/redis-cluster/redis1/data:/data- /root/docker/redis-cluster/redis1/redis.conf:/etc/redis.confcommand:redis-server /etc/redis.confdepends_on:- redis0redis2:image: rediscontainer_name: redis2restart: alwaysprivileged: truenetwork_mode: "host"volumes:- /root/docker/redis-cluster/redis2/data:/data- /root/docker/redis-cluster/redis2/redis.conf:/etc/redis.confcommand:redis-server /etc/redis.confdepends_on:- redis0redis3:image: rediscontainer_name: redis3restart: alwaysprivileged: truenetwork_mode: "host"volumes:- /root/docker/redis-cluster/redis3/data:/data- /root/docker/redis-cluster/redis3/redis.conf:/etc/redis.confcommand:redis-server /etc/redis.confdepends_on:- redis2redis4:image: rediscontainer_name: redis4restart: alwaysprivileged: truenetwork_mode: "host"volumes:- /root/docker/redis-cluster/redis4/data:/data- /root/docker/redis-cluster/redis4/redis.conf:/etc/redis.confcommand:redis-server /etc/redis.confdepends_on:- redis2sentinel1:image: rediscontainer_name: sentinel1restart: alwaysprivileged: truenetwork_mode: "host"volumes:- /root/docker/redis-cluster/sentinel1/sentinel.conf:/etc/sentinel.confcommand:redis-sentinel /etc/sentinel.confdepends_on:- redis0sentinel2:image: rediscontainer_name: sentinel2restart: alwaysprivileged: truenetwork_mode: "host"volumes:- /root/docker/redis-cluster/sentinel2/sentinel.conf:/etc/sentinel.confcommand:redis-sentinel /etc/sentinel.confdepends_on:- redis0sentinel3:image: rediscontainer_name: sentinel3restart: alwaysprivileged: truenetwork_mode: "host"volumes:- /root/docker/redis-cluster/sentinel3/sentinel.conf:/etc/sentinel.confcommand:redis-sentinel /etc/sentinel.confdepends_on:- redis0
  1. 最后,我们在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环境下查看虚拟机中搭建的哨兵状态

  1. 进入到 Redis 目录,在该目录下打开 cmd 命令行,运行 redis-cli.exe -h 192.168.88.130 -p 26379 -a root

image-20241009192901554

  1. 查看master节点的信息
sentinel master [sentinel集群名称]

image-20241009193355145

  1. 查看除自己之外,sentinel 集群中的其它 sentinel 节点信息
sentinel sentinels [sentinel集群名称]

image-20241009195419792

image-20241009195457636

  1. 查看slave节点的信息
sentinel slaves [sentinel集群名称]

image-20241009193715097

image-20241009193811267

  • 注:哨兵不直接支持级联从节点的监控(即哨兵一般不会监控从节点的从节点 - 我们所搭建的redis3和redis4),最佳实践通常是避免级联结构,使用简单的“主从”模式,减少管理和故障切换的复杂性。
  • 因此,我们搭建的redis集群如下:

image-20241009195201644

3、模拟master节点宕机

  1. 我们将主库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
  1. 我们再在sentinel中查看主从信息,便会发现主库更新,原本的redis0主库更换为从库。

三、RedisTemplate

  • 配置文件参考:
spring:data:redis:# 这里只需配置主节点的信息即可# RedisTemplate可以从主节点信息中获取从节点信息host: 192.168.88.130port: 6379password: rootjedis:pool:# 最大连接数max-active: 10# 最大空闲连接数max-idle: 5# 最小空闲min-idle: 1# 连接超时时间(毫秒)max-wait: 8000sentinel:password: rootmaster: jobsnodes: - 192.168.88.130:26379- 192.168.88.130:26479- 192.168.88.130:26579

个人问题记录:

  1. 在搭建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 

  1. 在模拟master节点宕机时:

因为我一开始搭建的是“主从从”模式集群,再在该基础上搭建哨兵集群,结构如下:

image-20241010111723147

哨兵不直接支持级联从节点的监控(即哨兵一般不会监控从节点的从节点 - 我们所搭建的redis3和redis4),但这时我们已经搭建好了,就不打算将redis3和redis4rm,我们先将redis0 stop再start,然后发现:

当 Redis 哨兵检测到主节点 redis0 不可用时,它将 redis2 切换为新的主节点。由于 redis3redis4 原本是 redis2 的从节点,这个链条并未断裂,且由于 redis2 成为了主节点,哨兵将其下的所有从节点(包括原本的从节点的从节点)也作为它的从节点进行管理

  • redis2 成为新的主节点后,redis1redis3、和 redis4 均会被识别为 redis2直接从节点,形成多层次的直接复制。

  • 因为哨兵在切换时没有自动重设 redis3redis4 的主从关系,它们仍然保持与 redis2 的连接。

  • 我们在RDM中对redis进行info replication,观察如下:

image-20241010112416474

  • 为什么没有redis0
    • redis0 作为 redis2 的从节点重新连接时,可能还没有完成所有的复制同步和状态更新。即使 redis0 成功连接为从节点,它的状态可能还在初始化过程中,导致暂时没有出现在 redis2 的从节点列表中。当我们再次尝试稍等片刻,然后再次使用 info replication 检查,就可以看到redis0也成为了redis2slave

当我们对其中一个sentinel进行sentinel slaves jobs操作后,发现:

image-20241009200231810

image-20241009200313041

image-20241009200352044

image-20241009200428858

  • 哨兵在切换后会将所有的下层节点(包括多级从节点)作为新的主节点的从节点进行管理。因此,当你在 sentinel slaves jobs 中查询时,能看到所有属于 redis2 直接或间接从属关系的节点(即 redis1redis3redis4 等),都被列为它的从节点。

因此,为了减少不必要的麻烦,我们会简化为一层“主-从”结构,以便哨兵更高效地管理复制关系。

参考博文:
Redis 哨兵集群搭建并使用 RedisTemplate 实现读写分离

参考书籍:
《Redis核心技术与实战》

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/811013.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

唯一客服浏览器插件: 视频号直播自动回复与循环发送话术-自动化插件

唯一客服浏览器插件 gofly.v1kf.com 我们在做视频号直播的时候,会有这种自动回复咨询问题的功能唯一客服浏览器插件现在就支持,在视频号直播后台,自动化回复用户问题,以及循环发送我们的介绍话术 十年开发经验程序员,离职全心创业中,历时三年开发出的产品《唯一客服系统》…

[编程笔记] 当前上下文中不存在名称ViewBag

当前上下文中不存在名称"ViewBag",很多ViewBag、@Html.Partial、@Html.FunctionBar() 等这些地方都报波浪线了,提示不存在这个名称,但是代码是可以运行的最近在弄另外一个项目,很长一段时间没接触MVC了,Visual Studio 2022识别cshtml文件的时候,出了一点故障!…

MSSQL-从字符串转换日期和/或时间时,转换失败

1、报错的sql为: select ID,Test_time as 时间, from ProcessData where convert(datetime,test_time,120) between convert(datetime, 2020-10-10, 120) and convert(datetime, 2024-10-11, 120) 它是将Test_time转化为datetime格式,再用between进行比较; 2、报错原因:…

Pytorch常用代码段汇总

Pytorch常用代码段来源: https://zhuanlan.zhihu.com/p/104019160 PyTorch最好的资料是官方文档。本文是PyTorch常用代码段,在参考资料[1](张皓:PyTorch Cookbook)的基础上做了一些修补,方便使用时查阅。 1. 基本配置 导入包和版本查询 import torch import torch.nn as nn…

manim边学边做--无向图

无向图属于数学中的图论这一学科, 所谓无向图G,就是由顶点集V(非空集合)和边集E(由V中元素构成的无序二元组的集合)组成的图, 可表示为G=(V,E)。 在无向图中,边没有方向,即从顶点A到顶点B的边与从顶点B到顶点A的边是相同的。 无向图简洁直观,常用于描述社交网络,交通…

[持续更新]程序员每天会阅读哪些技术网站(带链接)来提升自己?

本文原文来自[持续更新]程序员每天会阅读哪些技术网站(带链接)来提升自己? 国内的网站 这些国内技术网站和社区涵盖了编程语言、算法、职业规划、云计算、AI等多方面的内容,可以获取最新的技术资讯、学习资源和开发经验。当然目前国内的技术社区的内容还是相当的鱼龙混杂。CS…

PEPPA_CTH_PIG

你好CTH近日,有一PEPPA_HACKER_PIG黑入了某不知名CTH的博客,发现其博客荒凉至极,发怒而去,遂留此文,以记之。。。 这博客甚至连个分类也没有,只能我建一个了;

VScode远程访问虚拟机

下载vscode插件Remote Development 该插件包括了wsl,remote ssh 等四个插件,均是用于远程访问虚拟机。 通过ssh访问虚拟机 下载后在工具栏索引可以看到如下标识,按顺序点击进入,然后在“3”显示的搜索框通过“ ssh username@ipAddr”访问,这是方法一。 方法二,还可以通…

20222317 2024-2025-1《网络与系统攻防技术》实验一实验报告

一、实验内容 本次实验的对象是一个名为pwn1的linux可执行文件。该程序正常执行流程是:main调用foo函数,foo函数会简单回显任何用户输入的字符串。该程序同时包含另一个代码片段,getShell,会返回一个可用Shell。正常情况下这个代码是不会被运行的。我们本次实验将学习两种方…

似然

似然问题背景:我们观察到随机变量 \(Y\) 的值 \(y\),而 \(Y\) 的概率密度函数 \(f(y; \theta)\) 已知,但依赖于参数 \(\theta\)。 参数 \(\theta\) 来自参数空间 \(\Theta\),观测数据来自样本空间 \(\mathcal{Y}\)。 目标是根据观测数据 \(y\),推断参数 \(\theta\) 的可能…

05-蓝图(Blueprints)

Flask 的蓝图(Blueprints)是一种组织代码的机制,允许你将 Flask 应用分解成多个模块。这样可以更好地组织应用逻辑,使得应用更具可维护性和可扩展性。 每个蓝图可以有自己的路由、视图函数、模板和静态文件,这样可以将相关的功能分组。 通过使用蓝图,你可以将 Flask 应用…

组件间通信provide和inject

vue3提供两种方法,分别为(爷爷提供)provide(提供)和(孙子)inject(注入)。 可以实现隔辈传入数据,且孙子组件可以修改爷爷提供的数据。 即如果子组件再调用子组件,那么父组件可以通过provide 和 inject来实现父孙志坚消息通行。 ①实现父子组件调用子组件, 子组件再…