本文是大数据系列第 28 篇,详细介绍 ZooKeeper 的 ZNode 节点类型、内部数据结构、ZXID 事务 ID,以及 Watcher 监听机制的核心原理。
ZNode:ZooKeeper 的数据单元
ZooKeeper 以类 Unix 文件系统的树形结构组织数据,每个节点称为 ZNode。路径以 / 分隔,根节点为 /,例如 /app/config/db-host。
ZNode 内部结构
每个 ZNode 同时存储数据和元数据:
| 字段 | 说明 |
|---|---|
data | 字节数组,最大约 1 MB |
dataVersion | 数据版本号,每次 setData 后自增 |
cversion | 子节点版本号,子节点增删后自增 |
aclVersion | ACL 权限版本号 |
ctime | 节点创建时间戳 |
mtime | 节点最后修改时间戳 |
ephemeralOwner | 临时节点所属 Session ID;持久节点此字段为 0 |
numChildren | 子节点数量 |
ZNode 设计用于存储元数据和配置信息,不适合存储大业务数据。
ZNode 四种类型
1. 持久节点(Persistent)
创建后永久存在,直到显式删除。适合存储配置、服务元数据等需要长期保留的信息。
create /app/config "prod"
2. 持久顺序节点(Persistent Sequential)
自动在路径末尾追加 10 位递增序号,序号全局单调递增。
create -s /jobs/task "payload"
# 实际创建:/jobs/task0000000001
# 再次创建:/jobs/task0000000002
适用场景:分布式队列、有序任务分配。
3. 临时节点(Ephemeral)
与客户端 Session 生命周期绑定:Session 断开(超时或主动关闭)后,节点自动删除。临时节点不能有子节点。
create -e /services/instance-a "192.168.1.10:8080"
适用场景:服务注册(下线自动注销)、心跳检测。
4. 临时顺序节点(Ephemeral Sequential)
同时具备”自动删除”和”全局有序”特性,是实现公平分布式锁和 Leader 选举的核心原语。
create -e -s /lock/node "client-1"
# 实际创建:/lock/node0000000001
竞争锁时,序号最小的节点持有锁;锁持有者断开后,下一个序号的节点收到通知并获取锁。
ZXID:事务 ID
ZooKeeper 为每个写操作分配全局唯一的 64 位事务 ID(ZXID):
| 高 32 位(epoch)| 低 32 位(counter)|
- epoch(纪元):每次 Leader 选举后自增,标识当前 Leader 任期
- counter(计数器):当前 Leader 任期内的事务序号,每次写操作自增
- 全局单调递增:不同 epoch 之间通过高位保证总体有序
ZXID 的作用:
- ZAB 协议一致性:Follower 通过比较 ZXID 决定是否接受 Leader 的事务提案
- 崩溃恢复:节点重启后,通过比较 ZXID 从 Leader 同步缺失的事务
- 顺序保证:客户端请求按 ZXID 顺序执行,保障顺序一致性
Watcher 监听机制
Watcher 是 ZooKeeper 提供的事件驱动通知机制,允许客户端监听 ZNode 的变化。
核心特性
| 特性 | 说明 |
|---|---|
| 一次性触发 | Watcher 触发一次后自动失效,需重新注册 |
| 异步通知 | 通知不阻塞客户端正常操作 |
| 轻量级 | 通知内容只包含事件类型和节点路径,不含完整数据 |
| 有序性 | 同一客户端的事件通知按顺序到达 |
注册方式
# 注册数据监听
get -w /app/config
# 注册子节点监听
ls -w /services
触发事件类型
| 事件 | 触发条件 |
|---|---|
NodeCreated | 被监听的节点被创建 |
NodeDeleted | 被监听的节点被删除 |
NodeDataChanged | 节点数据被修改(setData) |
NodeChildrenChanged | 节点的子节点列表变化 |
实践演示
在一个终端中注册监听并等待:
zkCli.sh -server h121.wzk.icu:2181
# 在根节点写入数据,同时注册 Watcher
get -w /
在另一个终端修改数据:
zkCli.sh -server h122.wzk.icu:2181
set / wzk.icu
第一个终端会立即收到通知:
WATCHER::
WatchedEvent state:SyncConnected type:NodeDataChanged path:/
跨节点同步验证:数据写入任意节点后,其他所有节点立即可读到最新值,验证 ZAB 协议的强一致性。
Watcher 使用注意事项
- 必须重新注册:每次收到通知后,如果仍需监听,需立即调用
getData/getChildren/exists重新注册 - 通知可能丢失:在重新注册之前的变化不会触发通知,高频变更场景需结合轮询
- 轻量设计:通知不携带变更后的数据,客户端收到通知后需主动查询最新数据
小结
ZNode 的四种类型(持久/持久顺序/临时/临时顺序)构成了 ZooKeeper 所有高级特性的基础原语。ZXID 保障了全局写操作的顺序性,Watcher 一次性触发机制在低开销下实现了分布式事件通知。下一篇将通过命令行实践深入演示 Watcher 的注册与触发过程。