脑裂是怎么产生的
脑裂(Split-Brain)指集群中同时存在两个自认为有效的写入者:常见成因是网络分区让双方互相失联、心跳超时判定过早、旧主未被及时停止,或双活配置本身缺少仲裁。结果是两侧各自写入,数据在恢复后出现分叉,下游可能已按两份不同的历史执行了业务。防护的核心思路是让“有效写入者”唯一:多数派仲裁、租约与隔离(fencing)、存储端校验。
基本信息
| 成因 | 分区、心跳误判、旧主未及时停止、双活配置缺少仲裁 |
|---|---|
| 危害 | 双写冲突、数据回滚或丢失、下游重复处理 |
| 防护 | 多数派、租约 + fencing、共享存储校验、人工确认流程 |
| 验证手段 | 分区演练、时钟偏差注入、主从切换过程中的读写一致性检查 |
典型使用场景
- 数据库高可用切换:主库宕机后的自动提升与旧主隔离
- 跨数据中心双活:分区期间如何决定哪一侧可写
- 分布式锁与选主:验证锁服务在分区恢复后是否仍保持唯一有效持有者
- 容器编排中的工作负载接管:节点失联后的重新调度与旧实例隔离
- 存储多路径与共享卷:切换前确认旧主已被拒绝写入
排查与防护清单
- 检查仲裁:多数派规则是否生效,弱网时是否误判
- 检查隔离:旧主是否被 fencing 或存储端拒绝写入
- 检查双活:是否存在绕过仲裁的直写通道
- 对账预案:分区恢复后比对两侧数据并执行合并
- 演练验证:定期模拟分区,验证防护链完整
Fencing 令牌示意
Fencing 令牌示意
1. 主节点持有租约并获得单调递增的 fencing 令牌
2. 每次写请求携带令牌,存储端记录已见最大令牌
3. 存储端拒绝令牌小于等于已见最大值的写入
4. 租约过期后旧主即使仍在线,写入也会被存储端拒绝
# 关键:隔离由存储端强制,而不是依赖旧主自觉停止防护手段对照
| 手段 | 作用范围 | 失效条件 |
|---|---|---|
| 多数派仲裁 | 决定哪一侧可写 | 成员配置错误或分区后两侧都不足多数 |
| 租约 | 限定写权限的有效时间 | 依赖时钟,时钟回拨会破坏语义 |
| Fencing 令牌 | 存储端拒绝过期写入 | 存储不支持令牌校验则退化为逻辑约束 |
| 人工确认 | 异常恢复的兜底流程 | 响应慢,且依赖执行者的判断质量 |
跨数据中心双主在分区期间必然面临取舍:要么牺牲一侧可用性,要么接受冲突与合并成本;声称“既不停写又不冲突”的方案通常依赖未说明的假设。
脑裂预防的效果要靠演练证明:只读配置和文档无法确认旧主真的会被拒绝写入,需要在真实或准真实环境里模拟分区与切换。