11.5.4 Zab协议阶段:发现、同步与广播

Zab(ZooKeeper Atomic Broadcast)在选举完成后进入稳定运行,其核心目标是在主从架构下实现全局有序、可恢复的事务广播。Zab运行分为发现(Discovery)、同步(Synchronization)与广播(Broadcast)三阶段,构成从新Leader确立到对外稳定服务的完整路径。

文章图片

1. 发现阶段(Discovery)#

目的:确认新Leader权威、形成法定集合、建立新epoch。

关键动作:
- Follower向Leader发送FOLLOWERINFO,携带本地最新ZXID。
- Leader统计多数派,生成新epoch并广播给Follower。

示例:日志与状态观察

# 在Leader上查看选举与发现阶段日志(路径以发行版为准)
sudo tail -n 100 /var/log/zookeeper/zookeeper.out

# 典型日志片段(示例)
# INFO - leader elected, epoch=5
# INFO - FOLLOWERINFO received from server.3 zxid=0x50000012
# INFO - new epoch 5 established

命令解释:
- tail -n 100:查看最近100行日志,验证是否进入新epoch。
- 关注关键词:leader electedFOLLOWERINFOnew epoch

2. 同步阶段(Synchronization)#

目的:对齐日志与数据状态,让多数Follower具备一致前缀。

关键动作:
- Leader选择同步策略:Diff(增量)、Trunc(回滚)、Snap(快照全量)。
- Follower完成日志回放或加载快照后进入可提交状态。

示例:强制触发快照与观察同步

# 触发一次快照(4字命令,需在zoo.cfg中启用)
echo srvr | nc 127.0.0.1 2181

# 查看数据目录和日志目录(以默认路径为例)
ls -lh /var/lib/zookeeper
ls -lh /var/lib/zookeeper/version-2

# 观察最新snapshot与log文件
# snapshot.50000015
# log.50000010

命令解释:
- srvr:查看服务角色与ZXID,判断同步是否完成。
- snapshot.*:快照文件;log.*:事务日志。

排错要点:
- 同步耗时过长:检查磁盘IO、快照过大、snapCount过高。
- Follower反复Trunc:怀疑网络抖动或磁盘损坏导致日志不一致。

3. 广播阶段(Broadcast)#

目的:Leader处理写请求并提交到多数派,形成全序事务。

关键动作:
- Leader生成新ZXID并写入日志。
- 发送PROPOSAL给Follower,收到多数派ACK后发送COMMIT

示例:写入与提交观察

# 使用zkCli写入一个节点
/opt/zookeeper/bin/zkCli.sh <<'EOF'
create /zab_test "v1"
get /zab_test
EOF

# 使用四字命令查看统计信息
echo mntr | nc 127.0.0.1 2181 | egrep "zk_server_state|zk_zxid|zk_avg_latency"

命令解释:
- create /zab_test "v1":触发写请求。
- mntr:查看当前角色与ZXID变化,验证广播提交。

4. 阶段切换的关键条件#

  • 发现 → 同步:形成法定集合并确定新epoch。
  • 同步 → 广播:Leader确认多数Follower完成同步。
  • 同步未完成的节点不会对外提供写服务,确保一致性不被破坏。

5. 运维与故障视角的关注点#

常见现象与定位:
- 频繁进入发现/同步:网络抖动或心跳超时。
- 同步时间过长:日志过大或磁盘IO瓶颈。
- 广播延迟高:多数派ACK响应慢、Follower压力过高。

快速检查命令:

# 检查当前节点角色与延迟
echo srvr | nc 127.0.0.1 2181

# 观察会话数量与延迟
echo stat | nc 127.0.0.1 2181

6. 原理草图(读写与广播)#

sequenceDiagram
    participant C as Client
    participant L as Leader
    participant F1 as Follower1
    participant F2 as Follower2

    C->>L: write /x=v
    L->>L: log(ZXID)
    L->>F1: PROPOSAL
    L->>F2: PROPOSAL
    F1-->>L: ACK
    F2-->>L: ACK
    L->>F1: COMMIT
    L->>F2: COMMIT
    L-->>C: OK

7. 练习与验证#

  1. 验证发现阶段:重启Leader,观察日志中的new epochFOLLOWERINFO
  2. 验证同步策略:删除Follower日志目录后重启,观察快照同步触发。
  3. 验证广播提交:连续写入100个节点,观察zk_zxid单调递增。

练习命令示例:

# 批量写入100个节点
/opt/zookeeper/bin/zkCli.sh <<'EOF'
for i in {1..100}; do
  create /batch_$i "v$i"
done
EOF

# 观察ZXID变化
echo mntr | nc 127.0.0.1 2181 | egrep "zk_zxid"