← 返回题目列表

什么是脑裂?分布式系统如何避免脑裂?

高频 困难 第 16 / 27 题 更新于 2026/07/28
脑裂高可用QuorumFencing

简化版

脑裂是指集群因为网络分区、心跳误判或故障切换异常,出现两个或多个节点都以为自己是主节点,并同时对外提供写服务。它会造成数据分叉、重复调度、双主写入等严重问题。常见防护是多数派选主、租约、Fencing Token、STONITH/强制隔离、共享存储写保护、客户端只信任最新任期。

详细版

脑裂常见于主备、高可用、分布式锁、调度器、存储集群等场景。根因通常是:节点之间通信异常,但节点本身没有宕机,于是旧主和新主同时存在。

常见解决手段:

手段作用
多数派 Quorum只有拿到多数派的分区才能选主或写入
任期/epoch新主任期更大,旧主请求被拒绝
Fencing Token每次获得主身份拿到递增 token,下游只接受最大 token
租约 Lease主身份有有效期,过期必须续约成功才能继续写
STONITH/隔离确认旧主不可写后再让新主接管
共享存储保护存储层拒绝旧主写入

脑裂最怕“两个主都能写”。只靠心跳不足以避免脑裂,因为心跳断了不代表对方真的死了,可能只是网络隔离。

完整版教学

一、用主备切换理解脑裂

假设有一个主库 A 和备库 B。正常情况下 A 写数据,B 同步。现在 A 和 B 之间网络断了,B 收不到 A 的心跳,于是认为 A 挂了,自己提升为主。如果此时 A 其实还活着,并且客户端仍然能访问 A,那么 A 和 B 都在以主库身份写入,这就是脑裂。

脑裂的危险不是“有两个节点”,而是“两个节点都认为自己有权做不可重复的事情”。两个主库写同一份数据会产生冲突;两个调度器同时调度任务会重复执行;两个锁持有者同时操作资源会破坏互斥。

二、心跳为什么不能证明对方死亡

分布式系统里,收不到心跳只能说明“我现在联系不上对方”,不能说明“对方已经停止工作”。可能是网络丢包、交换机故障、安全组规则变化、GC 暂停、CPU 打满,也可能是自己这边网络有问题。

如果系统把“心跳超时”等同于“旧主死亡”,就很容易脑裂。正确设计要承认不确定性:联系不上旧主时,不能仅凭单点判断就让新主随便写,必须引入多数派、租约、隔离或下游 fencing。

三、多数派为什么能防止双主

如果集群有 3 个节点,任何主节点必须拿到至少 2 个节点认可。网络分区后,不可能出现两个分区都拿到多数派,因为两个多数派集合必然相交。这样少数派即使还活着,也不能继续作为主处理写请求。

Raft、ZooKeeper、etcd 都依赖类似思想。Leader 必须属于多数派,日志也要复制到多数派才能提交。这样即使少数派旧 Leader 还以为自己是 Leader,它也无法提交新的写入。

四、Fencing Token 是防脑裂的最后一道闸

多数派能减少脑裂,但在外部资源场景里,还需要 fencing。比如分布式锁保护的是数据库或文件系统,旧锁持有者可能因为长时间 GC 暂停而错过续约,锁被新客户端拿到。旧客户端恢复后,如果继续写外部资源,就破坏互斥。

Fencing Token 的做法是:每次成功获得锁或主身份时,发一个单调递增 token。外部资源只接受 token 更大的写请求,拒绝旧 token。这样即使旧主“醒过来”,也会被资源层挡住。这个思路在锁、调度、存储写入里非常重要。

五、租约和时钟的坑

租约看起来简单:主节点在租约有效期内才有权写。但租约依赖时间,如果机器时钟漂移或 GC 暂停,旧主可能误以为租约还有效。更稳的做法是租约续约要经过多数派确认,下游仍然校验 epoch/token。不要只靠本地时间判断自己是不是主。

六、工程上如何处理脑裂风险

第一,选主必须基于多数派,避免少数派独立称主。第二,主身份要有任期号,所有写请求带任期,下游拒绝旧任期。第三,关键外部资源要支持 fencing token。第四,故障切换前尽量隔离旧主,比如断电、停进程、取消挂载。第五,客户端要从权威注册中心或配置中心获取主地址,不能长期缓存旧主。

七、常见误区与追问

这道题不能只背概念,要把「脑裂问题」放回真实分布式系统里解释:谁发起、谁协调、状态如何变化、失败后怎么兜底,以及它和性能、可用性、一致性的取舍。

回答层次要讲清的内容容易漏掉的边界
核心结论脑裂是集群网络分区后多个节点都认为自己是主,导致双写和数据分叉不要停在名词解释
流程机制主节点与备节点网络中断 -> 备节点误判主故障并升主 -> 原主仍对外服务 -> 出现双主写入 -> 通过仲裁和 fencing 阻止旧主写说明触发方、参与方、状态变化和兜底
工程取舍主备集群网络隔离时,如果两个节点都对外写入,恢复后同一订单可能出现两个不同状态分布式基础题不能只背概念,必须落到网络不可靠、节点会故障、数据有副本这些前提
脑裂问题 面试拆解:
1. 主节点与备节点网络中断
2. 备节点误判主故障并升主
3. 原主仍对外服务
4. 出现双主写入
5. 通过仲裁和 fencing 阻止旧主写

记忆钩子:先定义问题,再说明一致性、可用性、分区、复制、时钟和故障模型的取舍;回答时要紧扣「脑裂问题」这道题,不要把相邻概念混成一段泛泛的分布式套话。

  • 误区:脑裂只是主从切换慢。 脑裂的核心是同时存在多个主并写入,数据会分叉。
  • 误区:心跳检测就能彻底避免脑裂。 心跳只能发现不可达,无法区分对方宕机还是网络分区。
  • 误区:恢复网络后自动合并就行。 双写数据可能冲突,必须有仲裁、隔离和人工修复策略。
  • 追问:如何防脑裂? 多数派仲裁、租约、fencing token、STONITH、只允许仲裁成功一侧写。
  • 追问:fencing 是什么? 给新主一个递增令牌,下游只接受最新令牌写入,旧主即使存活也写不进去。
  • 追问:为什么奇数节点常见? 多数派投票下奇数节点资源利用更高,3 节点可容忍 1 节点故障。

八、加强记忆

脑裂就是网络分区或误判导致多个节点都以为自己是主,并同时写同一资源。心跳超时不能证明对方死亡,所以不能只靠心跳切主。防脑裂的核心是:多数派保证只有一个分区有资格当主,任期/epoch 区分新旧主,Fencing Token 让外部资源拒绝旧主写入,必要时强制隔离旧主。关键点:选出新主不够,还要让旧主写不进去