请求处理链实测:用 jstack 看单机与集群节点的线程(NIO → RequestThrottler → ProcessThread → SyncThread → …),mntr 的平均耗时显示 fsync 是写路径的大头;leader 特有 ProcessThread / LearnerHandler,follower 特有 FollowerRequestProcessor;读在 follower 本地完成。
请求限流实测:20000 次流水线异步写默认 9089 次/秒;globalOutstandingLimit=10 降到 2723;request_throttle_max_requests=10 降到 3299(throttle 队列平均等待 266.0441 ms),=1 降到 492。
集群角色与请求路径实测(3 节点):leader 才有 zk_synced_followers;写通过 follower 要转发给 leader,但延迟差别被 fsync 淹没(5.03 vs 5.90 ms);读在连接的节点本地完成(连 follower 读 2000 次,leader 只多收 1 个包)。
Learner、Follower、Observer 的区别实测:observer 不投票、不算多数派(3 投票节点停 2 个即使还有 2 个 observer 也不能写);observer 接受写并转发给 leader;对写延迟有少量额外开销(5.95 → 7.21 ms)。
Observer 节点实战:连在 observer 上读 2000 次 leader 只多收 1 个包;停掉 2 个 observer 写入不受影响;observer 离线期间错过 2000 个事务,重启 557 ms 内以 DIFF 追上。
Quorum 多数派实测:3 / 4 / 5 个节点各杀不同数量,剩下的能否写——3 节点容忍 1 个,4 节点也只容忍 1 个(多数派 3),5 节点容忍 2 个;因此集群规模取奇数。
5 节点集群与容错数量实测:杀 follower 再杀 leader(2 个故障)后不到 1 秒恢复写入;已确认的 200 个写入全部保留;再杀 1 个失去多数派不可写,启动回 1 个节点(0.7 s)即恢复且数据完整。
QuorumPeer 状态机实测:LOOKING → FOLLOWING/LEADING → discovery → synchronization → broadcast;杀掉 leader 后存活节点约 +5 ms 进入 LOOKING,约 +216 ms 选出新 leader,约 +340 ms 完成同步;LOOKING 时 srvr 不服务;旧 leader 重启后以 follower 加入。
五节点 Quorum 检查表:对每个节点发 srvr / mntr 汇总角色、zxid、连接数、synced_followers;杀 follower 时 leader 的 synced_followers 4 → 3;杀 leader 后选举期间所有存活节点「不服务」,新 leader 的 zxid epoch +1;ruok 不能代表能否服务。
Leader 选举过程实测(3 节点,杀 leader 5 次):新 leader 出现中位 345 ms,第一次写入成功中位 410 ms(范围 373–811 ms);日志里的 Notification 展示选票交换:先投自己,再按比较规则改投。
FastLeaderElection 的选票比较实测:先比 epoch、再比 zxid、最后比 sid——落后的高 sid 节点落选、有最新数据的节点当选(z35-1);全新集群 5 次启动都是 2 号当选(谁先凑够多数派取决于启动时机)。
Leader 重新选举实测:杀 leader 5 次,持续写 / 读的客户端遇到的最长中断:写中位 445 ms(最小 379 / 最大 713)、读中位 432 ms;选举期间读写一起不可用。