🗒️哨兵机制
2024-9-20
| 2024-9-19
0  |  阅读时长 0 分钟
type
status
date
slug
summary
tags
category
icon
password

哨兵机制的基本流程

哨兵是就是 Redis 的一个进程,在主从实例运行时,它也在运行。哨兵负责三个任务:监控、选主(选择主库)、通知。
  1. 监控。
      • 周期性地向所有主从库发送 PING 命令,检测它们是否仍然在线运行。主从库在规定时间中,没有响应 PING 命令,哨兵会把其标记为“下线状态”。
      • 而当判定主库下线,会进入下一个流程──切换主库
  1. 选主。从众多从库中,按照一定规则选择一个从库实例,当作新的主库。
  1. 通知。
      • 哨兵将新主库的连接信息发送给其他从库,让它们执行 replicaof 命令,和新主库建立连接,并进行数据复制
      • 同时,哨兵将新主库的连接信息通知给客户端,让它们把请求发到新主库上。
哨兵需要做的两个决策:
  • 在监控任务中,哨兵需要判断主库是否处于下线状态;
  • 在选主任务中,哨兵也要决定选择哪个从库实例作为主库。

主观下线和客观下线

主观下线:单个哨兵通过主从库对 PING 命令的响应情况,判断主从库是否下线。
客观下线:多数哨兵,都判断主库已经“主观下线”,主库会被标记为“客观下线”。少数服从多数。
notion image

如何选择新主库?

  1. 筛选:在多个从库中,先按照一定的筛选条件,把不符合条件的从库去掉。
      • 筛选的条件
        • 检查从库的当前在线状态
        • 判断从库之前的网络连接状态
      • 具体操作:使用配置项 down-after-milliseconds * 10
        • down-after-milliseconds 是我们认定主从库断连的最大连接超时时间。如果在 down-after-milliseconds 毫秒内,主从节点都没有通过网络联系上,我们就可以认为主从节点断连了。
        • 如果发生断连的次数超过了 10 次,就说明这个从库的网络状况不好,不适合作为新主 库。
  1. 打分:按照一定的规则,给剩下的从库逐个打分,将得分最高的从库选为新主库
      • 打分规则:按照从库优先级从库复制进度从库 ID 号依次进行。只要在某一轮中,有从库得分最高,那么它就是主库了,选主过程到此结束。如果没有出现得分最高的从库,那么就继续进行下一轮。
      • 第一轮:优先级最高的从库得分高
        • 通过 slave-priority 配置项,给不同的从库设置不同优先级。
      • 第二轮:和旧主库同步程度最接近的从库得分高
        • 在主从库同步时的命令传播过程,主库会用 master_repl_offset 记录当前的最新写操作在 repl_backlog_buffer 中的位置,而从库会用 slave_repl_offset 这个值记录当前的复制进度。
          从库的 slave_repl_offset 最接近 master_repl_offset,那么它的得分就最高,可以作为新主库。
          💡
          主库都挂了,怎么获取主库的 master_repl_offset 值?
          master_repl_offset本身的理解没错,master_repl_offset是单调增加的,它的值可以大于repl_backlog_size。Redis会用一个名为repl_backlog_idx的值记录在环形缓冲区中的最新写入位置。举个例子,例如写入len的数据,那么
          master_repl_offset += len repl_backlog_idx += len
          但是,如果repl_backlog_idx等于repl_backlog_size时,repl_backlog_idx会被置为0,表示从环形缓冲区开始位置继续写入。而在实际的选主代码层面,sentinel 是直接比较从库的slave_repl_offset,来选择和主库最接近的从库。
          我的理解是 master_repl_offset 是单调递增的,是可以大于 repl_backlog_size,Redis 单独使用 repl_backing_idx 记录环形缓冲区中最新写入位置,而 repl_backing_idx 是循环递增的。当写入新数据时,两者的长度是都要变化的,不同的是,repl_backing_idx 等于 repl_backlog_size 时,会被置为 0。因此,在实际选主的时候,可以直接比较从库的 slave_repl_offset 即可。这个值谁最大,谁的得分高。
      • 第三轮:ID 号小的从库得分高
notion image

问题

问题 1:在主从切换过程中,客户端能否正常地进行请求操作呢?
对于读请求,有从库可以进行响应;写请求,需要等待确定完主库,才能正常响应。
问题 2:如果想要应用程序不感知服务的中断,还需要哨兵或客户端再做些什么吗?
对于读请求,需要哨兵和客户端协商,将请求打到从库上。对于写请求,那也没有办法,只能尽快选择新主库,哨兵与客户端及时协商新连接信息。

📎 参考

  • Redis
  • 哨兵集群主从库数据同步
    Loading...
    目录