9.5.1 三个定时监控任务

Redis Sentinel 通过三个定时监控任务完成对各个节点发现和监控:

  1. 每隔10秒, 每个 Sentinel 节点会向主节点从节点发送 info 命令获取最新的拓扑结构

image.png

作用:

  • 通过向主节点执行 info 命令, 获取从节点的信息,这也是为什么 Sentinel 节点不需要显式配置监控从节点
  • 当有新的从节点加入时都可以立刻感知出来
  • 节点不可达或者故障转移后, 可以通过 info 命令实时更新节点拓扑信息
  1. 每隔2秒, 每个 Sentinel 节点会向 Redis 数据节点sentinel:hello 频道上发送该 Sentinel 节点对于主节点的判断以及当前 Sentinel 节点的信息, 同时每个 Sentinel 节点也会订阅该频道, 来了解其他 Sentinel 节点以及它们对主节点的判断

image.png

作用:

  • 发现新的 Sentinel 节点: 通过订阅主节点的 sentinel:hello 了解其他的 Sentinel 节点信息, 如果是新加入的 Sentinel 节点, 将该 Sentinel 节点信息保存起来, 并与该 Sentinel 节点创建连接
  • Sentinel 节点之间交换主节点的状态, 作为后面客观下线以及领导者选举的依据

Sentinel 节点 publish 的消息格式如下:

  1. <Sentinel 节点 IP> <Sentinel 节点端口 > <Sentinel 节点 runId> <Sentinel 节点配置版本 >
  2. < 主节点名字 > < 主节点 Ip> < 主节点端口 > < 主节点配置版本 >
  1. 每隔1秒, 每个Sentinel 节点会向主节点从节点其余 Sentinel 节点发送一条 ping 命令做一次心跳检测, 来确认这些节点当前是否可达
    1. 通过上面的定时任务, Sentinel 节点对主节点、从节点、其余 Sentinel 节点都建立起连接, 实现了对每个节点的监控, 这个定时任务是节点失败判定的重要依据

image.png

9.5.2 主观下线和客观下线

1. 主观下线

主观下线是当前 Sentinel 节点的一家之言,存在误判的可能:

  • down-after-milliseconds 配置超时时间

image.png
图9-29 Sentinel节点主观下线检测

2. 客观下线

大部分 Sentinel 节点都对主节点的下线做了同意的判定, 那么这个判定就是客观的:

  • Sentinel 节点会通过 sentinel is-master-down-by-addr 命令向其他 Sentinel 节点询问对主节点的判断
  • 当超过 个数, Sentinel 节点认为主节点确实有问题

image.png

注意:

  • 从节点、Sentinel 节点在主观下线后, 没有后续的故障转移操作

sentinel is-master-down-by-addr 命令:

sentinel is-master-down-by-addr <ip> <port> <current_epoch> <runid>
  • ip: 主节点 ip
  • port: 主节点端口
  • current_epoch: 当前配置纪元
  • runid
    • 当 runid 等于 “*” 时, 作用是 Sentinel 节点直接交换对主节点下线的判定
    • 当 runid 等于当前 Sentinel 节点的 runid 时, 作用是当前 Sentinel 节点希望目标 Sentinel 节点同意自己成为领导者的请求

sentinel is-master-down-by-addr 命令的返回结果:

  • down_state: 目标 Sentinel 节点对于主节点的下线判断,1是下线,0是在线
  • leader_runid
    • 当 leader_runid 等于 “*” 时, 代表返回结果是用来做主节点是否不可达
    • 当 leader_runid 等于具体的 runid, 代表目标节点同意 runid 为领导者
  • leader_epoch: 领导者纪元

9.5.3 领导者 Sentinel 节点选举

在故障转移之前, Sentinel 之间进行领导者选举, 由领导者进行故障转移.

Redis 使用 Raft 算法, 大致过程:

  1. 每个在线的 Sentinel 节点都有资格成为领导者, 当它确认主节点主观下线时候, 会向其他 Sentinel 节点发送 sentinel is-master-down-by-addr 命令, 要求将自己设置为领导者
  2. 收到命令的 Sentinel 节点, 如果没有同意过其他 Sentinel 节点的 sentinel is-master-down-by-addr 命令, 将同意该请求, 否则拒绝
  3. 如果该 Sentinel 节点发现自己的票数已经大于等于 max(quorum, num(sentinels)/2+1), 那么它将成为领导者
  4. 如果此过程没有选举出领导者, 将进入下一次选举

image.png

s2 发起投票:

image.png

s3 发起投票:

image.png

实际上 Redis Sentinel 实现会更简单一些, 因为一旦有一个 Sentinel 节点获得了 max(quorum,num(sentinels)/2+1) 的票数, 其他 Sentinel 节点再去确认已经没有意义了, 因为每个 Sentinel 节点只有一票.

9.5.4 故障转移

步骤:

  1. 在从节点列表中选出一个节点作为新的主节点

选择方法:

a. 过滤: “不健康” (主观下线、断线)、5秒内没有回复过 Sentinel 节点 ping 响应、与主节点失联超过 down-after-milliseconds*10秒
b. 选择 slave-priority (从节点优先级) 最高的从节点列表, 如果存在则返回, 不存在则继续
c. 选择复制偏移量最大的从节点 (复制的最完整), 如果存在则返回, 不存在则继续
d. 选择 runid 最小的从节点

image.png

  1. Sentinel 领导者节点会对第一步选出来的从节点执行 slaveof no one 命令让其成为主节点
  2. Sentinel 领导者节点会向剩余的从节点发送命令, 让它们成为新主节点的从节点, 复制规则和 parallel-syncs 参数有关
  3. Sentinel 节点集合会将原来的主节点更新为从节点, 并保持着对其关注, 当其恢复后命令它去复制新的主节点