sentinel current_epoch必须全局单调递增,因其作为哨兵故障转移的任期编号,类比Raft term;每次选举或配置更新须用更大值,否则请求被拒;相同epoch会导致选主失败、脑裂。

sentinel current_epoch 为什么必须全局单调递增
因为 current_epoch 是哨兵集群做故障转移时的“任期编号”,类似 Raft 的 term。每次选举新主或执行配置更新,都必须用比当前所有已知 current_epoch 更大的值发起;否则其他哨兵会直接拒绝该请求。它不是时间戳,但必须严格递增——哪怕只是加 1。一旦两个哨兵各自生成了相同 epoch,就会导致选主失败、配置不一致、甚至脑裂。
quorum 和多数派投票如何防止 epoch 冲突升级
epoch 冲突本身不会自动“解决”,但哨兵通过两层约束把它压制在可控范围:
-
sentinel monitor mymaster 127.0.0.1 6379 2中的2(quorum)决定了:至少要有 2 个哨兵达成一致,才能将主节点标记为ODOWN,进而触发故障转移;这意味着单个哨兵擅自 bump epoch 并发起选举,会被其余哨兵无视 - 真正执行故障转移的哨兵(Leader),必须先通过
SENTINEL is-master-down-by-addr向其他哨兵拉票,且只有收到「多数派」(即 ≥ quorum)的1响应,才敢用新 epoch 启动 failover 流程 - 如果两个哨兵几乎同时尝试 bump epoch 并拉票,后发起的那个大概率收不到足够票数,其 epoch 请求被丢弃,不会写入集群状态
客观下线(ODOWN)确认前,epoch 冲突其实已被过滤掉
关键点在于:哨兵不会在 SDOWN 阶段就更新 current_epoch。只有当多个哨兵共同确认 ODOWN 后,当选 Leader 才会在发起 failover 前调用 sentinelEpoch++,并广播带新 epoch 的 SENTINEL CONFIG-REWRITE 请求。这个动作发生在共识形成之后,而非之前。所以所谓“epoch 冲突”,实际只存在于未被采纳的临时尝试中,不会污染集群共识状态。
运维上最容易忽略的点:手动修改配置后没重载或重启哨兵
如果你用 CONFIG SET 或编辑 sentinel.conf 改了 quorum、down-after-milliseconds 等参数,但没执行 SENTINEL CONFIG-REWRITE 或重启哨兵进程,那么不同哨兵持有的 current_epoch 可能长期不一致——因为它们从各自本地配置加载初始 epoch,而配置没同步。这种“静默不一致”比网络分区更难排查,故障转移时会突然暴露。











