哨兵机制

如果主库挂了,我们就需要运行一个新主库,比如说把一个从库切换为主库,把它当成主库。

在 Redis 主从集群中,哨兵机制是实现主从库自动切换的关键机制,它有效地解决了主从复制模式下故障转移的这三个问题。

基本任务

  1. 监控:主库真的挂了吗?
    a. 采用多实例组成的集群模式进行部署,这也被称为哨兵集群。
    b. 引入多个哨兵实例一起来判断,
  2. 选主:选择哪个从库作为主库?
    a. 通过在线状态、网络状况筛选掉一部分从库
    b. 再根据优先级、复制进度、从库的id进行打分
    c. 得分最高的就是新的主库
  3. 通知:把新主库的相关信息通知给从库和客户端

监控

哨兵进程在运行时,周期性地给所有的主从库发送 PING 命令,检测它们是否仍然在线运行。如果从库没有在规定时间内响应哨兵的 PING 命令,哨兵就会把它标记为“下线状态”;
同样,如果主库也没有在规定时间内响应哨兵的 PING 命令,哨兵就会判定主库下线,然后开始自动切换主库的流程。

选出新主库

主库挂了以后,哨兵就需要从很多个从库里,按照一定的规则选择一个从库实例,把它作为新的主库。

通知

  • 哨兵会把新主库的连接信息发给其他从库,让它们执行 replicaof 命令,和新主库建立连接,并进行数据复制。
  • 同时,哨兵会把新主库的连接信息通知给客户端,让它们把请求操作发到新主库上。

主观下线和客观下线

哨兵进程会使用 PING 命令检测它自己和主、从库的网络连接情况,用来判断实例的状态。

如果哨兵发现主库或从库对 PING 命令的响应超时了,那么,哨兵就会先把它标记为“主观下线”。

  • 从库响应超时,哨兵可以直接标记为“主观下线”
  • 主库需要哨兵集群一起判断,只有大多数的哨兵实例,都判断主库已经“主观下线”了,主库才会被标记为“客观下线”

客观下线标准:

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

重新选主

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

筛选条件

在选主时,除了要检查从库的当前在线状态,还要判断它之前的网络连接状态。

判断网络连接状态:
down-after-milliseconds 是我们认定主从库断连的最大连接超时时间。
如果在 down-after-milliseconds 毫秒内,主从节点都没有通过网络联系上,我们就可以认为主从节点断连了。如果发生断连的次数超过了 10 次,就说明这个从库的网络状况不好,不适合作为新主库。

三轮打分

按照从库优先级、从库复制进度以及从库 ID 号进行打分。只要在某一轮中,有从库得分最高,那么它就是主库了,选主过程到此结束。如果没有出现得分最高的从库,那么就继续进行下一轮。
  1. 优先级:slave-priority 配置项
  2. 复制进度:slave_repl_offset 最接近 master_repl_offset
  3. ID号:ID号最小的从库得分最高

小结

Redis 的哨兵机制自动完成了以下三大功能,从而实现了主从库的自动切换,可以降低 Redis 集群的运维开销:

  • 监控主库运行状态,并判断主库是否客观下线;
  • 在主库客观下线后,选取新主库;
  • 选出新主库后,通知从库和客户端。

问题:哨兵在操作主从切换的过程中,客户端能否正常地进行请求操作?
回答:如果客户端使用了读写分离,那么读请求可以在从库上正常执行,不会受到影响。但是由于此时主库已经挂了,而且哨兵还没有选出新的主库,所以在这期间写请求会失败,失败持续的时间 = 哨兵切换主从的时间 + 客户端感知到新主库 的时间。

08 哨兵集群

配置哨兵信息

sentinel monitor <master-name> <ip> <redis-port> <quorum> 

集群组成

哨兵实例之间可以相互发现,要归功于 Redis 提供的 pub/sub 机制,也就是发布 / 订阅机制。

哨兵只要和主库建立起了连接,就可以在主库上发布消息了,比如说发布它自己的连接信息(IP 和端口)。同时,它也可以从主库上订阅消息,获得其他哨兵发布的连接信息。

Redis 会以频道的形式,对这些消息进行分门别类的管理。
所谓的频道,实际上就是消息的类别。当消息类别相同时,它们就属于同一个频道。反之,就属于不同的频道。只有订阅了同一个频道的应用,才能通过发布的消息进行信息交换。

哨兵互连:
在主从集群中,主库上有一个名为“__sentinel__:hello”的频道,不同哨兵就是通过它来相互发现,实现互相通信的。

哨兵连接从库:
哨兵向主库发送 INFO 命令,主库接受到这个命令后,就会把从库列表返回给哨兵。
哨兵可以根据从库列表中的连接信息,和每个从库建立连接,并在这个连接上持续地对从库进行监控。

客户端事件通知

哨兵是一个运行在特定模式下的 Redis 实例,它并不服务请求操作,只是完成监控、选主和通知的任务。

每个哨兵实例也提供 pub/sub 机制,客户端可以从哨兵订阅消息。
哨兵提供的消息订阅频道有很多,不同频道包含了主从库切换过程中的不同关键事件。

客户端读取哨兵的配置文件后,可以获得哨兵的地址和端口,和哨兵建立网络连接。然后,我们可以在客户端执行订阅命令,来获取不同的事件消息。

举例:

  • 订阅“所有实例进入客观下线状态的事件”:SUBSCRIBE +odown
  • 订阅所有的事件:PSUBSCRIBE *

选举执行

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

    1. 拿到半数以上的赞成票
    2. 票数大于等于quorum

如果选举没有成功,那么这轮投票就不会产生 Leader。哨兵集群会等待一段时间(也就是哨兵故障转移超时时间的 2 倍),再重新选举。

注意:如果哨兵集群只有 2 个实例,此时,一个哨兵要想成为 Leader,必须获得 2 票,而不是 1 票。所以,如果有个哨兵挂掉了,那么,此时的集群是无法进行主从库切换的。因此,通常我们至少会配置 3 个哨兵实例。

小结

哨兵集群的关键机制:

  • 基于 pub/sub 机制的哨兵集群组成过程;
  • 基于 INFO 命令的从库列表,这可以帮助哨兵和从库建立连接;
  • 基于哨兵自身的 pub/sub 功能,这实现了客户端和哨兵之间的事件通知。

注意:要保证所有哨兵实例的配置是一致的,尤其是主观下线的判断值 down-after-milliseconds。

问题:Redis 1主4从,5个哨兵,哨兵配置quorum为2,如果3个哨兵故障,当主库宕机时,哨兵能否判断主库“客观下线”?能否自动切换?
回答:
1、哨兵集群可以判定主库“主观下线”。由于quorum=2,所以当一个哨兵判断主库“主观下线”后,询问另外一个哨兵后也会得到同样的结果,2个哨兵都判定“主观下线”,达到了quorum的值,因此,哨兵集群可以判定主库为“客观下线”。
2、但哨兵不能完成主从切换。哨兵标记主库“客观下线后”,在选举“哨兵领导者”时,一个哨兵必须拿到超过多数的选票(5/2+1=3票)。但目前只有2个哨兵活着,无论怎么投票,一个哨兵最多只能拿到2票,永远无法达到多数选票的结果。


IT小马
1.2k 声望166 粉丝

Php - Go - Vue - 云原生