脑裂(Split-Brain)

网络分区或旧主未停止时出现两个自认为有效的写入者,导致数据分叉;对策包括多数派仲裁、租约与隔离、fencing 令牌与存储端校验。

脑裂是怎么产生的

脑裂(Split-Brain)指集群中同时存在两个自认为有效的写入者:常见成因是网络分区让双方互相失联、心跳超时判定过早、旧主未被及时停止,或双活配置本身缺少仲裁。结果是两侧各自写入,数据在恢复后出现分叉,下游可能已按两份不同的历史执行了业务。防护的核心思路是让“有效写入者”唯一:多数派仲裁、租约与隔离(fencing)、存储端校验。

基本信息

成因分区、心跳误判、旧主未及时停止、双活配置缺少仲裁
危害双写冲突、数据回滚或丢失、下游重复处理
防护多数派、租约 + fencing、共享存储校验、人工确认流程
验证手段分区演练、时钟偏差注入、主从切换过程中的读写一致性检查

典型使用场景

  • 数据库高可用切换:主库宕机后的自动提升与旧主隔离
  • 跨数据中心双活:分区期间如何决定哪一侧可写
  • 分布式锁与选主:验证锁服务在分区恢复后是否仍保持唯一有效持有者
  • 容器编排中的工作负载接管:节点失联后的重新调度与旧实例隔离
  • 存储多路径与共享卷:切换前确认旧主已被拒绝写入

排查与防护清单

  • 检查仲裁:多数派规则是否生效,弱网时是否误判
  • 检查隔离:旧主是否被 fencing 或存储端拒绝写入
  • 检查双活:是否存在绕过仲裁的直写通道
  • 对账预案:分区恢复后比对两侧数据并执行合并
  • 演练验证:定期模拟分区,验证防护链完整

Fencing 令牌示意

Fencing 令牌示意
1. 主节点持有租约并获得单调递增的 fencing 令牌
2. 每次写请求携带令牌,存储端记录已见最大令牌
3. 存储端拒绝令牌小于等于已见最大值的写入
4. 租约过期后旧主即使仍在线,写入也会被存储端拒绝
# 关键:隔离由存储端强制,而不是依赖旧主自觉停止

防护手段对照

手段作用范围失效条件
多数派仲裁决定哪一侧可写成员配置错误或分区后两侧都不足多数
租约限定写权限的有效时间依赖时钟,时钟回拨会破坏语义
Fencing 令牌存储端拒绝过期写入存储不支持令牌校验则退化为逻辑约束
人工确认异常恢复的兜底流程响应慢,且依赖执行者的判断质量
跨数据中心双主在分区期间必然面临取舍:要么牺牲一侧可用性,要么接受冲突与合并成本;声称“既不停写又不冲突”的方案通常依赖未说明的假设。
脑裂预防的效果要靠演练证明:只读配置和文档无法确认旧主真的会被拒绝写入,需要在真实或准真实环境里模拟分区与切换。

易错点

  • 只依赖心跳超时切换,未做存储端隔离校验,旧主在恢复后继续写入
  • 双活写入冲突依赖时间戳覆盖,导致数据静默丢失且无法追溯
  • 仲裁成员数配置为偶数或分布不均,分区后两侧都认为自己具备多数
  • 租约实现依赖本地时钟,时钟回拨或漂移让租约语义失效
  • 切换流程无对账环节:分区恢复后直接接受两侧数据,冲突长期潜伏在业务数据里

数据来源与参考

  • 《数据密集型应用系统设计》(Kleppmann)第 8、9 章
  • Martin Kleppmann《How to do distributed locking》
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌