4. 故障转移流程详解:哨兵检测、主观下线、客观下线、Leader选举、从节点晋升

Redis Sentinel(哨兵)是 Redis 高可用架构的核心组件。当主节点发生故障时,哨兵集群通过一套严谨的分布式共识流程完成故障转移。整个流程分为五个关键阶段:哨兵检测、主观下线、客观下线、Leader 选举、从节点晋升。下面逐一拆解每个阶段的原理与实现细节。

4.1 哨兵检测:心跳与信息交换

每个哨兵节点以每秒一次的频率向所有已知的 Redis 实例(主节点、从节点、其他哨兵)发送 PING 命令,用于检测实例的存活状态。哨兵之间通过 __sentinel__:hello 频道交换彼此对主节点状态的认知。

关键参数:
  • down-after-milliseconds:哨兵判定实例主观下线的超时时间,默认 30000ms。
  • sentinel monitor <master-name> <ip> <port> <quorum>:定义监控的主节点及客观下线所需的投票数。

4.2 主观下线(Subjectively Down, SDOWN)

当单个哨兵节点在 down-after-milliseconds 时间内未收到主节点的有效 PONG 回复(或回复超时),该哨兵会将该主节点标记为主观下线。此状态仅代表该哨兵自身的判断,不涉及集群共识。

状态 触发条件 影响范围
SDOWN 单个哨兵 PING 超时 仅该哨兵本地标记
ODOWN 达到 quorum 数量的哨兵确认 SDOWN 整个哨兵集群共识

4.3 客观下线(Objectively Down, ODOWN)

当某个哨兵将主节点标记为 SDOWN 后,它会通过 SENTINEL is-master-down-by-addr 命令向其他哨兵发起投票询问,请求其他哨兵确认该主节点是否也处于 SDOWN 状态。当收到至少 quorum 个(含自身)哨兵确认后,该哨兵将主节点状态升级为客观下线,并触发故障转移流程。

quorum 设置建议: 对于 3 个哨兵的集群,quorum 通常设为 2;对于 5 个哨兵,quorum 设为 3。quorum 必须大于哨兵总数的一半,才能避免脑裂。

4.4 Leader 选举:Raft 风格的共识

一旦主节点被标记为 ODOWN,哨兵集群需要选举出一个 Leader 来负责执行实际的故障转移操作。选举过程基于 Raft 算法 的简化实现:

  1. 发起选举: 每个检测到 ODOWN 的哨兵都会将自己设置为候选人,并向其他哨兵发送投票请求(包含当前纪元 epoch)。
  2. 投票规则: 每个哨兵在每个纪元内只能投一票,遵循先到先得原则。哨兵会优先投票给请求中纪元最大的候选人。
  3. 选举获胜: 获得超过半数哨兵投票(即 majority,至少 N/2 + 1)的候选人成为 Leader。如果平票,则随机等待后进入下一轮选举。
  4. Leader 确认: 当选的 Leader 会获得一个唯一的 config-epoch,后续所有配置变更都以此纪元为准。
Redis 哨兵故障转移流程总览 Redis 哨兵故障转移流程总览 ① 哨兵检测 PING 心跳 ② 主观下线 SDOWN ③ 客观下线 ODOWN ④ Leader 选举 Raft 共识 ⑤ 从节点晋升 新主节点 流程说明: 1. 哨兵持续 PING 主节点,超时未响应则标记 SDOWN。 2. 哨兵向集群发起询问,达到 quorum 确认后升级为 ODOWN。 3. 哨兵集群基于 Raft 算法选举 Leader,获得多数票者胜出。 4. Leader 从从节点中选出数据最完整的一个晋升为新主节点。 5. 其余从节点切换复制目标到新主节点,完成故障转移。 6. 若原主节点恢复,自动降级为从节点。

4.5 从节点晋升:Leader 执行故障转移

当选的 Leader 负责执行具体的故障转移操作,步骤如下:

  1. 筛选从节点: Leader 从所有从节点中排除以下节点:
    • 处于 SDOWN 或 ODOWN 状态的从节点。
    • 最近一次与主节点通信时间超过 down-after-milliseconds 的从节点。
    • 优先级(slave-priority)为 0 的从节点(表示永不晋升)。
  2. 排序与选择: 对剩余从节点按以下优先级排序:
    1. 优先级(slave-priority)值越小越优先。
    2. 复制偏移量(replication offset)越大越优先,表示数据越新。
    3. 运行 ID(run ID)字典序越小越优先。
  3. 晋升操作: Leader 向选中的从节点发送 SLAVEOF NO ONE 命令,使其断开与旧主节点的复制关系,成为新的主节点。
  4. 配置更新: Leader 将新主节点的信息广播给所有哨兵,并更新 config-epoch。其他从节点通过 SLAVEOF 命令切换复制目标到新主节点。
注意: 如果原主节点在故障转移后恢复上线,哨兵会检测到它已成为一个从节点(因为其 runid 与当前主节点不一致),并自动将其配置为当前新主节点的从节点,避免出现双主脑裂。

4.6 故障转移时序与关键参数

阶段 耗时估算 关键配置 说明
哨兵检测 持续进行 sentinel monitor 每秒 PING 一次
主观下线 down-after-milliseconds down-after-milliseconds 默认 30s
客观下线 毫秒级(网络延迟) quorum 投票确认
Leader 选举 毫秒~秒级 failover-timeout Raft 选举
从节点晋升 毫秒级 slave-priority 执行 SLAVEOF NO ONE
Leader 选举与从节点晋升详细流程 Leader 选举与从节点晋升详细流程 Leader 选举(Raft 简化) 哨兵 A(候选人) 哨兵 B(投票) 哨兵 C(投票) Leader(哨兵 A) ① 哨兵 A 检测到 ODOWN,发起选举 ② 哨兵 B、C 投票给 A(先到先得) ③ A 获得 3 票(超半数),成为 Leader ④ Leader 获得 config-epoch 控制权 从节点晋升 旧主节点(故障) 新主节点 从节点 1 从节点 2 ① Leader 筛选从节点(排除故障/优先级0) ② 按优先级→复制偏移量→run ID 排序 ③ 向最优从节点发送 SLAVEOF NO ONE ④ 其他从节点切换复制到新主节点

4.7 故障转移后的数据一致性保证

故障转移过程中,可能存在部分数据未同步到新主节点的情况。Redis 哨兵采用异步复制,因此无法保证强一致性。但在大多数场景下,通过以下机制保证最终一致性:

  • 复制偏移量优先: 选择数据最完整的从节点晋升,最大限度减少数据丢失。
  • 客户端重定向: 故障转移后,哨兵通过 switch-master 事件通知客户端,客户端重新连接新主节点。
  • 原主节点降级: 原主节点恢复后自动成为从节点,从新主节点同步数据,补全丢失的写入。
生产建议: 对于需要更高数据安全性的场景,可以启用 min-slaves-to-write 和 min-slaves-max-lag 参数,限制主节点在从节点数量不足或复制延迟过大时拒绝写入,减少故障转移时的数据丢失风险。