ZooKeeper 适合保存少量协调元数据,不是通用数据库。学会它的关键是把 znode、会话和通知看成一个整体:状态由节点保存,所有权由会话表达,Watch 只负责提示“可能变化了”。
Table of contents
Open Table of contents
znode 不是文件
ZooKeeper 的命名空间像目录树,例如 /services/payment/instance-0001。每个 znode 同时拥有路径、少量字节数据、子节点和版本元数据。更新时传入期望版本,可实现比较并交换;版本不匹配说明有人抢先修改,客户端应重新读取再决定。
| 创建模式 | 会话结束后删除 | 名称追加序号 | 常见用途 |
|---|---|---|---|
| persistent | 否 | 否 | 配置、根目录 |
| ephemeral | 是 | 否 | 在线实例、所有权 |
| persistent sequential | 否 | 是 | 持久有序记录 |
| ephemeral sequential | 是 | 是 | 选主、锁候选者 |
临时节点绑定会话,不是 TCP 连接。短暂断线期间会话可能仍有效;超过会话超时后,服务端删除临时节点。网络恢复前,客户端不能武断地认为自己仍是 Leader。
Watch 是失效通知
传统 Watch 通常触发一次。正确循环是:读取数据并注册 Watch;收到事件后再次读取并重新注册;重连后重新同步。通知可能合并,你不能靠“收到 3 次事件”推导“发生了 3 次修改”。ZooKeeper 也提供持久 Watch,但业务仍应以重新读取后的状态为准。
// 伪代码:通知只唤醒读取,不携带完整真相。
void refresh() {
byte[] latest = client.getData().usingWatcher(event -> refresh()).forPath(path);
apply(latest);
}
真实 Java 项目通常使用 Apache Curator 管理连接、重连和 recipe。阅读ZooKeeper 当前文档时,重点核对会话、顺序保证和 Watch 章节;复制示例前确认服务端与客户端版本兼容。
先写故障断言
你至少要测试:断网但未过会话超时、会话确实过期、回调执行慢、重复通知、初次读取与注册之间的竞态。应用状态应允许全量重建,不能只靠增量事件维持。
下一步
继续阅读08-05 ZooKeeper 配置、选主、锁与注册发现,把这些原语组合成可用的协调方案。