bigywater.tech
ZooKeeper · 94

Curator LeaderLatch

Curator 有两套选主:LeaderLatch(当选后一直当,直到你关闭)和 LeaderSelector(按次轮流)。这篇都跑一遍:主动让位多快、服务端不可达时 leader 的反应、轮转是否公平、进程崩溃后多久换主。

6–11 ms
close() 当前 leader 后新 leader 出现
SUSPENDED
服务端冻结时 leader 在此刻就放弃领导权(会话超时前)
2.6–3.5 s
kill -9 leader 进程后新 leader 开始工作的空窗

LeaderLatch:干净让位

实测 · 本机执行输出
  启动后 leader = C0;hasLeadership 为 true 的候选数 = 1;getParticipants = [C0*, C1, C2, C3, C4]
  close() C0 → 新 leader C1,11 ms
  close() C1 → 新 leader C2,6 ms
  close() C2 → 新 leader C3,6 ms
  close() C3 → 新 leader C4,8 ms

与 kazoo 的 Election 同源(临时顺序节点,序号最小者当选);Curator 的 LeaderLatch 提供 hasLeadership() 和监听回调。

服务端不可达时 leader 怎么办

实测 · 本机执行输出
  0.0s isLeader
  0.5s 冻结服务端 5 s
  4.1s notLeader
  4.1s STATE SUSPENDED
  5.5s 解冻
  5.9s STATE RECONNECTED
  5.9s isLeader
  最后 hasLeadership = true

默认的 ConnectionStateErrorPolicy 把 SUSPENDED 也当成「可能丢了领导权」,所以 leader 在 SUSPENDED 时就停手。这避免了「leader 已不是 leader 还在干活」的窗口,代价是网络抖动会让 leader 短暂中断(这里恢复后又当选)。

LeaderSelector:轮流

实测 · 本机执行输出
  各候选当 leader 的次数:{S0=7, S1=7, S2=6};前 12 次轮换顺序:[S0, S1, S2, S0, S1, S2, S0, S1, S2, S0, S1, S2]

进程崩溃

实测 · 本机执行输出
  kill -9 P2 → 新 leader P0,最后一次心跳到新 leader 开始 2.56 s
  kill -9 P0 → 新 leader P4,最后一次心跳到新 leader 开始 3.49 s
  kill -9 P4 → 新 leader P3,最后一次心跳到新 leader 开始 3.49 s
  期间同时有两个进程在发 leader 心跳的采样点数:0

和会话超时的关系:临时节点要到会话过期才删除,所以空窗至少接近会话超时。要更快的切换,只能缩短会话超时(代价是更容易误判)。

分步演示

Curator 选主
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 / ZooKeeper 3.9.6(brew 安装的 jar,用 java -cp 直接启动自己的实例,OpenJDK 17 Temurin,JVM 堆 128 MiB)/ 本机回环端口 7300+,数据在临时目录;默认 tickTime=2000;计时用 time.perf_counter,数字每次运行会有小幅抖动。Curator 5.7.1 + OpenJDK 17;第 1–3 项会话超时 6 s,第 4 项 3 s;冻结服务端用 kill -STOP / -CONT
    • 没有验证:ConnectionStateErrorPolicy 的其它取值(只对 LOST 敏感)下的行为、LeaderSelector 的 takeLeadership 被中断时的细节、真实网络分区、选主节点数很多(上百)时的惊群
    京ICP备2026067502号-1京公网安备11010502063487号