真实的网络分区不是「立刻断开」而是「悄悄丢包」。这篇用一个会丢弃节点间流量的 TCP 代理把 leader 隔离出去,按毫秒记录各节点的角色变化,以及分区两侧的写入各是什么结果。
+ -1001 ms z47-1 → follower + -1001 ms z47-2 → leader + -1000 ms z47-3 → follower + 926 ms z47-1 → 不服务 + 927 ms z47-2 → 不服务 + 928 ms z47-3 → 不服务 + 7926 ms z47-1 → follower + 7927 ms z47-3 → leader + 8032 ms z47-1 → 不服务 + 8358 ms z47-3 → 不服务 + 8903 ms z47-1 → follower + 8904 ms z47-2 → follower + 8905 ms z47-3 → leader (隔离发生在 +0 ms;恢复网络在 +8010 ms)
代理有两种断网方式:立刻关闭连接(检测很快),或悄悄丢包(要等超时)。我最先用了前者,发现节点几乎立刻就发现了故障,这与真实分区不同,所以改成了丢包。
当前 leader = z47-3(被隔离的就是它)
多数派一侧的客户端 create /from-majority:成功(带重试)(分区后 1277 ms 完成,含故障检测与重新选举)
被隔离的旧 leader 上的那次 create /from-isolated,3 秒后:ready = True
网络恢复后,被隔离侧那次 create 的结果: ConnectionLoss
恢复后读两个路径:/from-majority → True | /from-isolated → False
各节点 Mode: {'z47-1': 'follower', 'z47-2': 'leader', 'z47-3': 'follower'} | Zxid: {'z47-1': '0x400000002', 'z47-2': '0x400000002', 'z47-3': '0x400000002'}