哨兵机制

哨兵机制是实现主从库自动切换的,主要解决主从复制模式下故障转移。比如下面的问题

主库真的挂了吗?该选择哪个从库作为主库?怎么把新主库的相关信息通知给从库和客户端呢?

哨兵主要任务就是三个任务:监控、选主(选择主库)和通知

监控

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

选主

监控判断主库挂了之后,就需要从很多从库按照一定规则选择一个从库作为主库。

通知

哨兵选主之后,需要把主库链接信息发给从库,让它们执行replicaof命令和新库建立连接并且进行数据的复制。并且 哨兵还会把新的主库连接信息发给客户端,让它们的请求发到新的主库上。

主从库下线判断

哨兵进程会使用PING命令检测自己和主从库连接情况,判断实例的状态。如果哨兵发现主库或者从库对PING命令的响应超时,哨兵就会把实力标记为下线。

如果是从库标记下线就可以,因为从库下线不会影响太大。

主库下线,需要进行主从切换。有时候会出现哨兵误判,其实主库并没有下线。误判一般会出现网络集群压力较大、网络阻塞或者说主库压力较大。

那怎么减少误判呢?

通常会采用哨兵集群模式,多个哨兵一起判断,就可以避免单个哨兵因为自身网络不好,误判主库下线。多个哨兵判断原则就是少数服从多数。当有 N 个哨兵实例时,最好要有 N/2 + 1 个实例判断主库为“主观下线”,才能最终判定主库为下线。

如何选择主库

选主的条件是筛选+打分。

筛选条件

选主的时候需要进行从库当前在线状态和判断它之前的网络状态。如果从库和主库总是断连,说明这个从库网络不好。

具体怎么判断呢?

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

打分条件

从库打分分为三轮规则: 从库优先级、从库复制进度以及从库ID号。如果有一轮从库得分高,那它一定是主库了,如果都一样就进行下一轮打分。

第一轮:优先级最高的从库得分高

用户可以通过 slave-priority 配置项,给不同的从库设置不同优先级。

第二轮:和旧主库同步程度最接近的从库得分高。

主从库同步时有个命令传播的过程。在这个过程中,主库会用 master_repl_offset 记录当前的最新写操作在 repl_backlog_buffer 中的位置,而从库会用 slave_repl_offset 这个值记录当前的复制进度。

此时,我们想要找的从库,它的 slave_repl_offset 需要最接近 master_repl_offset。如果在所有从库中,有从库的 slave_repl_offset 最接近 master_repl_offset,那么它的得分就最高,可以作为新主库。

第三轮:ID 号小的从库得分高。

每个实例都会有一个 ID,这个 ID 就类似于这里的从库的编号。目前,Redis 在选主库时,有一个默认的规定:在优先级和复制进度都相同的情况下,ID 号最小的从库得分最高,会被选为新主库。

回顾流程

首先,哨兵会按照在线状态、网络状态,筛选过滤掉一部分不符合要求的从库,然后,依次按照优先级、复制进度、ID 号大小再对剩余的从库进行打分,只要有得分最高的从库出现,就把它选为新主库。

哨兵集群

如果有哨兵实例在运行时发生了故障,主从库还能正常切换吗?

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

为了实现主从切换,我们引入了哨兵;为了避免单个哨兵故障后无法进行主从切换,以及为了减少误判率,又引入了哨兵集群;哨兵集群又需要有一些机制来支撑它的正常运行。

支持哨兵集群的这些关键机制,包括:

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

对于主从切换,当然不是哪个哨兵想执行就可以执行的,否则就乱套了。所以,这就需要哨兵集群在判断了主库“客观下线”后,经过投票仲裁,选举一个 Leader 出来,由它负责实际的主从切换,即由它来完成新主库的选择以及通知从库与客户端。