直接回答:网络分区让两个节点各自认为对方已死、同时接管主角色,双侧同时接受写入导致数据分叉——脑裂。fencing(隔离/栅栏)确保“失效的主真的失效”:让它无法再接触共享资源——断电(IPMI 强制关机)、禁用交换机端口、撤销存储挂载权限、或租约过期后存储层拒绝其写令牌。没有 fencing 的主备切换等于赌博。

展开解析:经典场景拆解:共享存储数据库主备——主网络抖动失联,备提升为主继续写;旧主其实活着也在写同一存储,数据文件互相覆盖损坏。fencing 手段分层:资源级——存储层的 SCSI persistent reservation / NVMe 写令牌,新主先“抢占并封锁”旧主的写权限再接管,存储配合则绝对可靠;节点级——STONITH(shoot the other node in the head,IPMI/iLO 远程断电),暴力但确定;租约级——主持有分布式锁租约(etcd lease),失联即租约过期自动释放,新主确认租约已过期才接管,配合 fence 令牌(fence token 单调递增,存储只认最新令牌的写,陈旧主的写被拒)形成完整闭环。时钟陷阱:租约依赖“过期时间”判断,GC 停顿(Java 进程的 30 秒 STW)让持有者在“自己视角租约未过期”但实际已过期后继续写——这正是 Martin Kleppmann 质疑 Redis Redlock 的核心案例,对策就是 fence token 让下游资源自己做最终裁决。工程纪律:主备切换脚本必须含 fencing 步骤并验证完成;能用共识协议(Raft)的组件就别用手工主备——多数派机制内建防双主。

追问方向:fence token 为什么必须是存储层校验而非客户端自觉?GC 停顿为何能击穿租约?

(约 500 字)