7.2 搭建哨兵模式的集群

在上文提到的主从复制模式的集群里,一方面可以提升数据的安全性,比如主服务器失效后,可以启动从服务器上的备份数据,另一方面也可以通过读写分离来提升性能.但是当主服务器发生故障后,需要手动进行数据恢复动作.比如让应用程序连到从服务器上,同时需要重新设置主从关系.

也就是说,基于主从复制模式的集群在发生故障时可能会出现数据丢失等情况,对此可以在主从模式的基础上再引入"哨兵(Sentinel)"机制,一方面用哨兵进程监控主从服务器是否可用,另一方面当主服务器故障发生时通过哨兵机制可以实现"故障自动恢复"的效果.

7.2.1 哨兵模式概述

一般来说,哨兵机制会和主从复制模式整合使用,在基于哨兵的模式里会在一台或多台服务器上引入哨兵进程,这些节点也叫哨兵节点

哨兵节点一般不存储数据,它的作用是监控主从模式里的主服务器节点.当哨兵节点监控的主服务器发生故障时,哨兵节点会主导"故障自动恢复"的流程,具体来讲就是会在该主服务器下属的从服务器中选出一个新的主服务器,并完成相应的数据和配置更改动作

也就是说,如果采用这种模式,可以让故障自动修复,从而提升系统的可用性.在项目中,一般会配置多个主从模式集群,所以会引入多个哨兵节点.如下图示:

基于哨兵模式的集群

多个哨兵相互监控的目的:

当一个Sentinel节点检测到Redis主服务器可能出现问题时,它不会立即采取行动.相反,它会询问其他Sentinel节点以验证其观察结果.只有当足够数量的Sentinel节点同意主服务器出现问题时(这是通过sentinel monitor配置中的仲裁值定义的),故障转移过程才会开始

此外,Sentinel节点之间的通信还有其他几个目的:

  1. 选举新的领导者:当主服务器被认为是下线的并且需要进行故障转移时,Sentinel节点之间会进行选举,选择一个Sentinel作为领导者来执行故障转移

  2. 配置同步:当一个Sentinel节点检测到主服务器的配置更改(例如IP地址或端口更改)时,它会通知其他Sentinel节点

  3. 状态信息共享:Sentinel节点之间会定期交换关于它们监视的Redis服务器的状态信息

为了实现Sentinel之间的这种通信,你需要确保Sentinel配置中的sentinel announce-ipsentinel announce-port已正确设置,并且所有Sentinel节点都可以互相访问.这通常在启动Sentinel时会自动进行,但在某些网络配置或Docker环境中可能需要手动设置


7.2.2 搭建哨兵模式集群

  • step1. 按7.1小节的步骤启动一个1主2从的redis集群

  • step2. 编写哨兵节点1的配置文件

  • step3. 启动哨兵节点1容器

创建容器:

查看容器状态:

  • step4. 进入哨兵节点1容器,查看哨兵节点信息

其中:

  • status=ok:主节点状态为ok

  • slaves=2:该主节点有2个从节点

  • sentinels=1:该主节点有1个哨兵

  • step5. 编写哨兵节点2的配置文件

  • step6. 启动哨兵节点2容器

启动容器:

查看容器状态:

  • step7. 进入哨兵节点2容器,查看哨兵节点信息

可以看到,此时有2个哨兵节点在监视该集群了

集群架构如下图示:

哨兵集群架构图

2个哨兵节点同时监控Redis主节点(即:redis-master).Redis主节点和从节点之间依然存在数据同步的复制模式.

7.2.3 哨兵节点的常用配置

  • sentinel down-after-milliseconds:该配置项指定了Sentinel认为Redis服务器(无论是主服务器还是从服务器)已下线之前,它应该在多长时间内无法与该服务器通信.具体来说,这是Sentinel判断Redis实例为"主观下线"的时间阈值."主观下线"是Sentinel内部的术语,意思是一个Sentinel个体认为一个Redis实例已经下线,但它还没有与其他Sentinel个体达成一致来确认这一点.当一个Redis实例被标记为"主观下线"后,Sentinel会询问其他Sentinel节点,以确认该实例是否真的下线.只有当超过配置中定义的Sentinel数量(例如sentinel monitor 中定义的仲裁值)同意该实例已下线时,它才会被标记为"客观下线".一旦一个主服务器被标记为"客观下线",故障转移过程就会开始

  • sentinel failover-timeout:定义了故障转移的超时时间.其作用如下:

  1. 故障转移超时:如果一个故障转移操作开始但在这个超时时间内没有完成,那么该操作将被中止.这确保了故障转移不会永远地挂起,特别是在出现网络分区或其他复杂问题的情况下

  2. 重新尝试故障转移:如果因某种原因故障转移失败(例如没有足够的从服务器或网络问题),Sentinel将在这个超时时间后再次尝试故障转移

  3. 保护已经发生的故障转移:如果在故障转移完成后,原主服务器重新上线但是作为从服务器,Sentinel会在failover-timeout期间保护新的主服务器不被其他旧的主服务器替代.这样可以防止频繁的角色切换

  4. 配置同步:此超时时间还决定了在首次尝试同步配置和其他状态信息失败后,Sentinel之间多久会再次尝试同步

  • step1. 修改哨兵节点1的配置文件

  • step2. 重启哨兵节点1容器

重启容器:

查看容器状态:

  • step3. 修改哨兵节点2的配置文件

  • step4. 重启哨兵节点2容器

重启容器:

查看容器状态:

7.2.4 哨兵模式下的故障自动恢复效果

本小节中由于容器的读写问题,故直接使用了宿主机来模拟故障自动恢复的流程:

注:使用哨兵模式要求主从节点的用户名和密码要一致,故需要先修改2个从节点的用户名和密码

  • step1. 修改slave1.conf

  • step2. 修改slave2.conf

  • step3. 启动1主2从,共3个进程,模拟一个redis集群

  • step4. 修改sentinel_1.conf和sentinel_2.conf

  • step5. 启动哨兵节点

  • step6. 查看哨兵监控的主从状态

可以看到,此时哨兵监视的主节点为127.0.0.1:6379

  • step7. 中断主节点的redis-server进程

  • step8. 查看哨兵监控的主从状态

可以看到,2个哨兵节点都判定主节点已经无法连接了,到达了配置文件中设定的仲裁值

  • step9. 再次查看哨兵监控的主从状态

可以看到,此时已经将1个从节点提升为主节点了

  • step10. 在redis-slave1.conf对应的进程中查看主从情况

可以看到,该节点已经被提升为主节点了

  • step11. 在redis-slave2.conf对应的进程中查看主从情况

可以看到,该节点现在从属于127.0.0.1:6380了.说明故障自动恢复动作已经完成

7.2.5 通过日志观察故障恢复流程

查看哨兵节点1的日志:

其中:

  • 17785:X 17 Aug 2023 13:44:20.854 # +sdown master redis-master-node 127.0.0.1 6379:sdown表示主观下线

  • 17785:X 17 Aug 2023 13:44:20.915 # +odown master redis-master-node 127.0.0.1 6379 #quorum 2/2:odown表示客观下线.

    • #quorum 2/2:表示仲裁值为2,已经达到仲裁值了,故判定主节点客观下线

  • 17785:X 17 Aug 2023 13:44:20.918 # +try-failover master redis-master-node 127.0.0.1 6379:开始启动故障恢复流程

  • 故障恢复的各个流程如下:

  • 17785:X 17 Aug 2023 13:44:22.938 # +switch-master redis-master-node 127.0.0.1 6379 127.0.0.1 6380:表示已经哨兵已经操作集群切换了主节点

  • 切换主节点后加载集群中的其他节点:

查看哨兵节点2的日志:

其中:

可以看到主观下线的部分是相同的,但后续哨兵节点2并没有进行操作.这是因为只能由1个哨兵节点完成故障自动恢复的动作,因此如果有多个哨兵节点同时监控到主节点失效,最终只能有1个哨兵节点通过竞争得到执行故障恢复操作的权限

从两个哨兵节点的日志中可以看到,故障恢复操作的权限最终被哨兵节点1竞争得到,因此当哨兵节点2发现主节点失效后,只能停留在主观下线(sdown)阶段,无法继续进行故障恢复操作.只有当哨兵节点1完成故障恢复操作后,哨兵节点2才能再次感知到重构后的主从复制模式集群,并继续监控该集群中的节点.日志如下:

7.2.6 故障节点恢复后的表现

  • step1. 编辑master.conf

由于故障节点会作为从节点恢复到集群中,所以需要配置主节点的用户名和密码(其实这个应该在最初就配置进去).如果不配置,虽然后续也能加入集群,但是无法同步数据

  • step2. 再次启动之前的redis-master进程

  • step3. 登录该节点,查看主从状态

可以看到,该节点自动以从节点的身份接入了集群

哨兵节点1的日志如下:

哨兵节点2的日志如下:

从中大家能看到,哨兵节点不仅能自动恢复故障,而且当故障节点恢复后会自动把它重新加入到集群中,而无须人工干预.也就是说,与简单的"主从复制模式集群"相比,基于哨兵模式的集群能很好地提升系统的可靠性

Last updated