redis|主库挂了,如何不间断服务((哨兵机制))

在主从集群模式下,如果从库发生了故障,客户端可以继续向主库或其他从库发送请求,进行相关操作;但如果主库挂了,就会直接影响到从库的同步,因为从库没有相应的主库可以进行数据复制。
如果客户端发送的都是读操作,还可以由其他从库继续提供服务,在纯读环境下还能被接受。但如果是写操作,需要由主库来完成写操作,此时主库挂了不能继续服务写操作请求了。如下图:redis|主库挂了,如何不间断服务((哨兵机制))
文章图片

无论是无法写操作,还是无法进行数据同步,都是不能接受的。所以如果主库挂了,就需要有一个新的主库,把一个从库切换为主库。这里边涉及了一些问题:

  1. 主库真的挂了吗?
  2. 该选择哪个从库作为主库?
  3. 怎么把新主库的相关信息通知给从库和客户端呢?
所以出现了哨兵机制。在 redis 主从集群中,哨兵机制有效的解决了故障转移的问题。
哨兵机制的基本流程 哨兵是一个运行在特殊模式下的 redis 进程,主从库实例同时运行时,它也在运行。哨兵的三个主要任务:监控、选主和通知。
监控是指哨兵进程在运行时,周期性的给所有的主从库发送 PING 命令,检测它们是否仍然在线运行。如果主从库没有在规定时间内响应哨兵的 PING 命令,哨兵就会记为“下线状态”。如果是主库没有及时响应,就会进入“选主”。哨兵从多个从库里按照一定的规则选择一个从库实例,作为新的主库。然后进入“通知”。在执行通知任务时,哨兵会把新主库的连接信息发给其他从库,让它们执行 replicaof 命令,和新主库建立连接,并进行数据复制。同时,哨兵会把新主库的连接信息通知给客户端,让它们把请求操作发到新主库上。
redis|主库挂了,如何不间断服务((哨兵机制))
文章图片

哨兵的三个任务中,通知任务比较简单,只需要把新主库的信息发送给从库和客户端,让它们和新主库建立连接就行,并不涉及决策的逻辑。但是,在监控和选主两个任务中,哨兵需要额外的逻辑:
  • 在监控任务中,哨兵需要判断主库是否处于下线状态
  • 在选主任务中,哨兵也要决定选择哪个从库实例作为主库
主观下线和客观下线 哨兵进程会使用 PING 命令检测自己和主从库的网络连接情况。如果主从库响应超时,哨兵就会把它标记为“主观下线”。
如果是从库的话,哨兵简单的标记为“主观下线”就可以,因为从库一般对集群影响不大。
如果是主库,哨兵不能简单的标记为“主观下线”。因为可能存在一个情况:哨兵误判。其实主库并没有故障,但是一旦启动了主从切换,后续的选主和通知操作就会带来额外的开销。
所以要特别注意误判的情况。
哨兵机制采用多实例组成的集群模式进行部署,也被称为哨兵集群。引入多个哨兵实例一起判断,避免单个哨兵因为自身网络状况不好,而误判主库下线的情况。同时由于有多个哨兵,出现不稳定的概率较小。哨兵机制采用少数服从多数的方法,只有大多数哨兵实例都判断主库已经“主观下线”了,主库才会被标记为“客观下线”。如下图所示:
redis|主库挂了,如何不间断服务((哨兵机制))
文章图片

比如当有 N 个哨兵时,最好有 N/2 + 1 个实例判断主库为“主观下线”,才能最终判定主库“客观下线”,这样能避免误判带来的主从切换。
如何选定新主库? 哨兵选主的过程:“筛选 + 打分”。先从多个从库按照一定的筛选条件,把不符合条件的从库去掉,然后按照一定的规则,对剩下的从库逐个打分,将得分最高的从库选为新主库,如下图所示:
redis|主库挂了,如何不间断服务((哨兵机制))
文章图片

筛选:首先要保证所选的从库仍然在线运行,并且是稳定运行。除了检查该从库当前的在线状态,还要判断它之前的网络连接状态。如果从库总是和主库断连,而且断连次数超过一定的阈值,那么这个从库的网络状态并不是很好,就可以把这个从库筛掉了。
具体怎么判断呢?使用配置项 down-after-millseconds * 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,那它的得分就最高,可以作为新主库。如图:
redis|主库挂了,如何不间断服务((哨兵机制))
文章图片

从库2将选为主库。
第三轮:id号小的从库得分高
在优先级和复制进度相同的情况下,id号最小的从库得分最高,会被选为新主库。
【redis|主库挂了,如何不间断服务((哨兵机制))】到这里,“选主”过程就完成了。

    推荐阅读