🗒️哨兵集群
2024-9-20
| 2024-9-19
0  |  阅读时长 0 分钟
type
status
date
slug
summary
tags
category
icon
password
配置哨兵的命令

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

哨兵实例之间可以相互发现,要归功于 Redis 提供的 pub/sub 机制,也就是发布 / 订阅
机制。在主从集群中,主库上有一个名为“__sentinel__:hello”的频道,不同哨兵就是通过
它来相互发现,实现互相通信的。哨兵只要和主库建立起了连接,就可以在主库上发布消息了,比如说发布它自己的连接信息(IP 和端口)。同时,它也可以从主库上订阅消息,获得其他哨兵发布的连接信息。当多个哨兵实例都在主库上做了发布和订阅操作后,它们之间就能知道彼此的 IP 地址和端口。
notion image
上述是与主库建立连接,那如何与从库建立建立呢?
这是由哨兵向主库发送 INFO 命令来完成的。
  1. 哨兵给主库发送 INFO 命令
  1. 主库接受到这个命令后,就会把从库列表返回给哨兵。
  1. 哨兵根据从库列表中的连接信息,和每个从库建立连接,并在这个连接上持续地对从库进行监控。
notion image
通过 pub/sub 机制,哨兵之间可以组成集群,同时,哨兵又通过 INFO 命令,获得了从库连接信息,也能和从库建立连接,进行监控。

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

哨兵就是一个运行在特定模式下的 Redis 实例(进程),只不过它并不服务请求操作,只是完成监控、选主和通知的任务。所以,每个哨兵实例也提供 pub/sub 机制,客户端可以从哨兵订阅消息。哨兵提供的消息订阅频道有很多,不同频道包含了主从库切换过程中的不同关键事件。
重要的频道汇总在了一起,涉及几个关键事件,包括主库下线判断、新主库选定、从库重新配置。
notion image
客户端订阅消息步骤
  1. 客户端读取哨兵的配置文件,获得哨兵的地址和端口,和哨兵建立网络连接
  1. 在客户端执行订阅命令,来获取不同的事件消息
获取完消息,我们就可以使用消息了,例如当新主库选择出来后,客户端会看到 switch-master 事件,得到新主库的连接信息,从而与新主库连接。

由哪个哨兵执行主从切换?──“投票仲裁”

“客观下线”的具体步骤:

  1. 当哨兵判断主库“主观下线”后,就会给其他哨兵发送 is-master-down-by-addr 命令
  1. 其他哨兵会根据自己和主库的连接情况,做出 Y 或 N 的响应,Y 相当于赞成票,N 相当于反对票。
  1. 一个哨兵获得了仲裁所需的赞成票数后,就可以标记主库为“客观下线”。这个所需的赞 成票数是通过哨兵配置文件中的 quorum 配置项设定的。──
    1. 没有说明超过半票
  1. 此时,这个哨兵就可以再给其他哨兵发送命令,表明希望由自己来执行主从切换,并让所 有其他哨兵进行投票。这个投票过程称为“Leader 选举”。──谁发现谁成为

Leader 选举

成为 Leader 的哨兵,满足两个条件:
  1. 拿到半数以上的赞成票;
  1. 拿到的票数同时还需要大于等于哨兵配置文件中的 quorum
Leader 选举过程:每人有且只有一票,投给自己或他人。如果某一轮没有哨兵满足成为 Leader 的条件,那么这轮投票就不会产生 Leader。哨兵集群会等待一段时间(也就是哨兵故障转移超时时间的 2 倍),再重新选举。
notion image
  1. 在 T1 时刻,S1 判断主库为“客观下线”,它想成为 Leader,就先给自己投一张赞成票,然后分别向 S2 和 S3 发送命令,表示要成为 Leader。
  1. 在 T2 时刻,S3 判断主库为“客观下线”,它也想成为 Leader,也先给自己投一张赞成票,再分别向 S1 和 S2 发送命令,表示要成为 Leader。
  1. 在 T3 时刻,S1 收到了 S3 的 Leader 投票请求。因为 S1 已经给自己投了一票 Y,所以它不能再给其他哨兵投赞成票了,所以 S1 回复 N 表示不同意。同时,S2 收到了 T2 时 S3 发送的 Leader 投票请求。因为 S2 之前没有投过票,它会给第一个向它发送投票请求的哨兵回复 Y,给后续再发送投票请求的哨兵回复 N,所以,在 T3 时,S2 回复 S3,同意 S3 成为 Leader。
  1. 在 T4 时刻,S2 才收到 T1 时 S1 发送的投票命令。因为 S2 已经在 T3 时同意了 S3 的投票请求,此时,S2 给 S1 回复 N,表示不同意 S1 成为 Leader。发生这种情况,是因为 S3 和 S2 之间的网络传输正常,而 S1 和 S2 之间的网络传输可能正好拥塞了,导致投票请求传输慢了。
  1. 最后,在 T5 时刻,S1 得到的票数是来自它自己的一票 Y 和来自 S2 的一票 N。而 S3 除了自己的赞成票 Y 以外,还收到了来自 S2 的一票 Y。此时,S3 不仅获得了半数以上的 Leader 赞成票,也达到预设的 quorum 值(quorum 为 2),所以它最终成为了 Leader。接着,S3 会开始执行选主操作,而且在选定新主库后,会给其他从库和客户端通知新主库的信息。
注意:主库被标记为客观下线是由多个 Sentinel 达成一致后确定的,这是一个前提条件。在确认 客观下线后,会立即触发领导者选举,但这两个步骤是依次进行而非同时发生。且主库切换只能由 Leader 来执行。
我想再给你分享一个经验:要保证所有哨兵实例的配置是一致的,尤其是主观下线的判断值 down-after-milliseconds。我们曾经就踩过一个“坑”。当时,在我们的项目中,因为这个值在不同的哨兵实例上配置不一致,导致哨兵集群一直没有对有故障的主库形成共识,也就没有及时切换主库,最终的结果就是集群服务不稳定。所以,你一定不要忽略这条看似简单的经验。

问题

问题 1:5 个哨兵实例的集群,quorum 值设为 2。在运行过程中,如果有 3 个哨兵实例都发生故障了,此时,Redis 主库如果有故障,还能正确地判断主库“客观下线”吗?如果可以的话,还能进行主从库自动切换吗?
我觉得应该可以。5 个哨兵有 3 个哨兵发生了故障,还有 2 个哨兵可以正常工作。只要两票都选择同一个哨兵,就可以判断“客观下线”。同样,可以进行主从切换。
可以正确判断“客观下线”。无法进行主从切换。在选择 Leader 时,需要满足两个条件。但是由于有 3 个哨兵实例挂了,只有两个存活,半数以上哨兵同意是 3 票,这条件永远无法完成,也就无法进行主从切换了。
问题 2:哨兵实例是不是越多越好呢?如果同时调大 down-after-milliseconds 值,对减少误判是不是也有好处?
我认为不是。哨兵实例越多,确实可以降低误判率,且有更大地故障兜底能力。但是,在判断“客观下线”和选举 Leader 时,可能会导致网络拥堵,选举的时间也会变长。
 
 
 

📎 参考

  • Redis
  • 切片集群哨兵机制
    Loading...
    目录