Redis的高可用方案离不开哨兵系统,而哨兵之间如何达成共识、何时真正把流量切到从节点,核心就在于quorum仲裁机制。很多人在配置哨兵时只抄了样例里的quorum数值,却并不清楚这个数值在故障判定链路里到底卡在哪一环。理解quorum,要从单个哨兵的本地判断和多个哨兵的协同确认两个层面来看。

主观下线、客观下线与quorum的衔接逻辑
每个哨兵节点都会周期性地向Redis主节点发送PING命令,如果在配置的down-after-milliseconds时间内连续没有收到有效回复,该哨兵就会在本地将主节点标记为“主观下线”,也就是SDOWN。这一步完全是个体的独立判断,并不依赖其他哨兵,所以任何网络瞬断都可能让某一个哨兵单独认为主库挂了。
主观下线本身不会触发故障转移,真正起作用的是“客观下线”(ODOWN)。当某个哨兵发现主节点SDOWN后,会向其他哨兵发送sentinel is-master-down-by-addr命令询问意见。如果包括自己在内,认同主节点不可达的哨兵数量达到配置文件里写的quorum值,发起者就会把主节点标记为客观下线,这时候才具备切换资格。quorum就是这道仲裁门槛,它决定了“几个人说不行才算真的不行”。
需要注意,quorum只负责认定客观下线,不负责选新主库。选主库还需要在哨兵内部再走一轮基于Raft变体的领导者选举,而领导者选举要求获得“多数派”支持,也就是超过半数哨兵同意。因此quorum可以小于半数,但客观下线后能否顺利选Leader,仍受总节点数和半数规则的约束。
quorum数值设置对系统行为的具体影响
假设部署了3个哨兵,如果quorum设为2,那么只要2个哨兵认为主节点挂了就能客观下线,这在单节点网络异常时仍能较灵敏地切换。但若quorum设为1,任意1个哨兵的误判都会直接引发切换,极大增加脑裂和误切风险。反过来,若哨兵有5个而quorum设为5,则必须全部确认,任何一人失联都会导致无法切换,可用性反而下降。
实践中常见的建议是:quorum设为哨兵总数的半数以上、但小于总数,例如3节点设2,5节点设3或4。这样既可容忍个别哨兵抖动,又不会因门槛过低而误动。此外,如果机房发生了网络分区,少数派分区内的哨兵即便达到quorum也无法凑齐领导者选举的多数,因此不会在两边各切一次主,quorum配合多数派规则共同抑制了脑裂。
下面是一段简化的哨兵配置示例,展示了quorum的写法以及与其配合的超时参数:
# sentinel.conf 片段 sentinel monitor mymaster 127.0.0.1 6379 2 sentinel down-after-milliseconds mymaster 5000 sentinel failover-timeout mymaster 10000 # 上面数字2即quorum,表示至少2个哨兵确认主节点不可达
从源码与消息交互看仲裁过程
在Redis哨兵的实现中,每个哨兵维护着对其他哨兵认知主节点状态的计数。当收到sentinel is-master-down-by-addr的回复时,会将同意的票数累加,并与自身的quorum比较。代码层面,sentinel.c里的sentinelCheckObjectivelyDown函数就承担了这一累加与判定。只要masters->flags中SDOWN标记存在,且票数不小于quorum,便置上ODOWN标记。
这种基于 gossip 风格询问加本地计票的方式,避免了强一致协议的开销,但也意味着quorum是一个“弱门槛”:它不保证全局瞬时一致,只保证在多数哨兵存活时,误判概率随quorum增大而迅速降低。我们可以在模拟网络延迟的测试中观察到,quorum为2的3节点集群,在注入30毫秒随机丢包时,误切次数远低于quorum为1的集群。
为了直观对比不同配置,可以参考下面的参数影响表:
| 哨兵总数 | quorum值 | 容忍失效哨兵数 | 误切风险 |
|---|---|---|---|
| 3 | 1 | 0 | 高 |
| 3 | 2 | 1 | 中 |
| 5 | 3 | 2 | 低 |
| 5 | 5 | 0 | 极低但易不切换 |
可以看出,quorum并非越大越好,而是要在故障发现速度和误判容忍度之间找平衡。结合领导者选举所需的多数派,在规划集群时应当先定哨兵总数,再反推一个既大于网络抖动容忍度、又明显小于总数的quorum,才能构建出真正稳健的Redis仲裁体系。