9.5.1 三个定时监控任务
Redis Sentinel 通过三个定时监控任务完成对各个节点发现和监控:
- 每隔10秒, 每个 Sentinel 节点会向主节点和从节点发送 info 命令获取最新的拓扑结构
作用:
- 通过向主节点执行 info 命令, 获取从节点的信息,这也是为什么 Sentinel 节点不需要显式配置监控从节点
- 当有新的从节点加入时都可以立刻感知出来
- 节点不可达或者故障转移后, 可以通过 info 命令实时更新节点拓扑信息
- 每隔2秒, 每个 Sentinel 节点会向 Redis 数据节点的 sentinel:hello 频道上发送该 Sentinel 节点对于主节点的判断以及当前 Sentinel 节点的信息, 同时每个 Sentinel 节点也会订阅该频道, 来了解其他 Sentinel 节点以及它们对主节点的判断
作用:
- 发现新的 Sentinel 节点: 通过订阅主节点的 sentinel:hello 了解其他的 Sentinel 节点信息, 如果是新加入的 Sentinel 节点, 将该 Sentinel 节点信息保存起来, 并与该 Sentinel 节点创建连接
- Sentinel 节点之间交换主节点的状态, 作为后面客观下线以及领导者选举的依据
Sentinel 节点 publish 的消息格式如下:
<Sentinel 节点 IP> <Sentinel 节点端口 > <Sentinel 节点 runId> <Sentinel 节点配置版本 >
< 主节点名字 > < 主节点 Ip> < 主节点端口 > < 主节点配置版本 >
- 每隔1秒, 每个Sentinel 节点会向主节点、从节点、其余 Sentinel 节点发送一条 ping 命令做一次心跳检测, 来确认这些节点当前是否可达
- 通过上面的定时任务, Sentinel 节点对主节点、从节点、其余 Sentinel 节点都建立起连接, 实现了对每个节点的监控, 这个定时任务是节点失败判定的重要依据
9.5.2 主观下线和客观下线
1. 主观下线
主观下线是当前 Sentinel 节点的一家之言,存在误判的可能:
- down-after-milliseconds 配置超时时间
图9-29 Sentinel节点主观下线检测
2. 客观下线
大部分 Sentinel 节点都对主节点的下线做了同意的判定, 那么这个判定就是客观的:
- Sentinel 节点会通过 sentinel is-master-down-by-addr 命令向其他 Sentinel 节点询问对主节点的判断
- 当超过
个数, Sentinel 节点认为主节点确实有问题
注意:
- 从节点、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 算法, 大致过程:
- 每个在线的 Sentinel 节点都有资格成为领导者, 当它确认主节点主观下线时候, 会向其他 Sentinel 节点发送 sentinel is-master-down-by-addr 命令, 要求将自己设置为领导者
- 收到命令的 Sentinel 节点, 如果没有同意过其他 Sentinel 节点的 sentinel is-master-down-by-addr 命令, 将同意该请求, 否则拒绝
- 如果该 Sentinel 节点发现自己的票数已经大于等于 max(quorum, num(sentinels)/2+1), 那么它将成为领导者
- 如果此过程没有选举出领导者, 将进入下一次选举
s2 发起投票:
s3 发起投票:
实际上 Redis Sentinel 实现会更简单一些, 因为一旦有一个 Sentinel 节点获得了 max(quorum,num(sentinels)/2+1) 的票数, 其他 Sentinel 节点再去确认已经没有意义了, 因为每个 Sentinel 节点只有一票.
9.5.4 故障转移
步骤:
- 在从节点列表中选出一个节点作为新的主节点
选择方法:
a. 过滤: “不健康” (主观下线、断线)、5秒内没有回复过 Sentinel 节点 ping 响应、与主节点失联超过 down-after-milliseconds*10秒
b. 选择 slave-priority (从节点优先级) 最高的从节点列表, 如果存在则返回, 不存在则继续
c. 选择复制偏移量最大的从节点 (复制的最完整), 如果存在则返回, 不存在则继续
d. 选择 runid 最小的从节点
- Sentinel 领导者节点会对第一步选出来的从节点执行 slaveof no one 命令让其成为主节点
- Sentinel 领导者节点会向剩余的从节点发送命令, 让它们成为新主节点的从节点, 复制规则和 parallel-syncs 参数有关
- Sentinel 节点集合会将原来的主节点更新为从节点, 并保持着对其关注, 当其恢复后命令它去复制新的主节点