bigywater.tech
ZooKeeper · 32

QuorumPeer 状态机

每个 ZooKeeper 节点内部有一个状态机(QuorumPeer):它在 LOOKING、FOLLOWING、LEADING、OBSERVING 之间切换。这篇不画状态图,直接把节点日志里的 Peer state changed 按时间排出来。

4 个状态
LOOKING / FOLLOWING / LEADING / OBSERVING
约 0.35 s
杀掉 leader 到新一任进入 broadcast 的时间(本机,3 节点)
LOOKING = 不服务
srvr 返回 not currently serving requests

启动时的状态变化

实测 · 本机执行输出
  +    0 ms  Peer state changed: following
  +    6 ms  FOLLOWING - LEADER ELECTION TOOK - 430 MS
  +    7 ms  Peer state changed: following - discovery
  +   14 ms  Peer state changed: following - synchronization
  +   15 ms  Peer state changed: following - synchronization - diff
  +   17 ms  Peer state changed: following - synchronization
  +   39 ms  Peer state changed: following - broadcast

leader 被杀之后

实测 · 本机执行输出
  z32-1(现在 follower):
    +  -81 ms  Peer state changed: following - broadcast
    +    4 ms  Peer state changed: looking
    +  216 ms  Peer state changed: following
    +  217 ms  FOLLOWING - LEADER ELECTION TOOK - 213 MS
    +  218 ms  Peer state changed: following - discovery
    +  331 ms  Peer state changed: following - synchronization
    +  332 ms  Peer state changed: following - synchronization - snap
    +  336 ms  Peer state changed: following - synchronization
    +  344 ms  Peer state changed: following - broadcast
  z32-3(现在 leader):
    +  -64 ms  Peer state changed: following - broadcast
    +    5 ms  Peer state changed: looking
    +  216 ms  Peer state changed: leading
    +  223 ms  LEADING - LEADER ELECTION TOOK - 218 MS
    +  226 ms  Peer state changed: leading - discovery
    +  332 ms  Peer state changed: leading - synchronization
    +  343 ms  Peer state changed: leading - broadcast

时间点来自日志时间戳与我脚本里记录的「杀」的时刻(同一台机器),所以相对值可信,绝对值有毫秒级误差。

状态与对外表现

实测 · 本机执行输出
  LOOKING → 还没有 leader,在选举(此时 srvr 返回「不在服务」);FOLLOWING / LEADING / OBSERVING → 对应 Mode follower / leader / observer
  重新启动原 leader 0.3 秒后看它的 srvr: Mode: follower
  几秒后: follower

分步演示

QuorumPeer 状态
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 / ZooKeeper 3.9.6(brew 安装的 jar,用 java -cp 直接启动自己的实例,OpenJDK 17 Temurin,JVM 堆 128 MiB)/ 本机回环端口 7300+,数据在临时目录;默认 tickTime=2000;计时用 time.perf_counter,数字每次运行会有小幅抖动。3 节点伪集群;状态变化取自节点日志(INFO),杀 leader 用 kill -9
    • 没有验证:OBSERVING 状态的变化(第 28 篇只验证了角色)、选举反复失败时的状态(第 38 篇)、状态机的内部实现
    京ICP备2026067502号-1京公网安备11010502063487号