❓它解决什么问题
分布式系统里,有一类"小但难"的需求反复出现:谁是 Master?配置变了怎么通知?谁拿到了锁?ZK 把这些"协调逻辑"统一封装好,让你专注业务。
ZK 提供的核心能力
① 统一命名 / 服务注册发现:节点把地址写进 ZNode,别人来读。
② 配置管理:配置放 ZNode,变更后自动推送。
③ 分布式锁 / 选主:用临时有序节点实现。
④ 集群状态感知:节点上下线通过会话/临时节点自动反映。
定位:ZK 存储的是"元数据(小数据)",不是业务大块数据。单节点通常有配额限制(默认 1MB/节点),当作"分布式的小记事本"。
🌳数据模型:ZNode 树
ZK 的数据是一棵层级树,每个节点叫 ZNode,路径如 /service/order/node1。
节点类型:持久(Persistent) / 临时(Ephemeral,会话断开即删) / 顺序(Sequential,自动追加单调递增序号)。分布式锁、选主靠"临时+顺序"节点实现:谁序号最小谁是 Master。
🤝一致性:ZAB 协议
ZK 的一致性由 ZAB(ZooKeeper Atomic Broadcast)保证,本质是一种为 ZK 定制的原子广播/主备协议(和 Raft 同源思路)。
ZAB 的两个阶段
① 崩溃恢复(选主):Leader 挂了,剩余 Follower 选出新 Leader,并同步已提交的事务(类似 Raft 选举 + 日志匹配)。
② 消息广播(原子广播):正常时 Leader 把写请求按 ZXID 顺序发给所有 Follower,多数派 ACK 后提交。
顺序一致(Sequential Consistency):ZK 保证从同一客户端发出的写操作按序生效,且所有客户端看到的更新顺序一致。它不是线性一致(写有广播延迟),但足够支撑协调场景。
👀Watcher 监听机制
客户端可以对 ZNode 注册 Watcher,节点变化(创建/删除/数据变更)时 ZK 主动推送一次通知。
关键特性:Watcher 是一次性的——触发后即失效,需重新注册(所以客户端要"循环监听")。这避免了 ZK 长期维护大量监听带来的压力。
典型误用:"为什么配置改了没收到?"——多半是 Watcher 触发后没重新注册,或者用了
getData 而非 exists 导致节点不存在时无法监听创建事件。🛠️典型用途与实现套路
| 用途 | 实现 |
|---|---|
| 分布式锁 | 在 /lock 下创建临时顺序节点,序号最小者获锁;释放=删节点或断会话 |
| Master 选主 | 同上,最小的临时顺序节点即 Master;宕机会话断→节点消失→重新选举 |
| 服务注册发现 | 服务启动时在 /services 下建临时节点;消费者监听该目录变化 |
| 配置中心 | 配置存 ZNode,客户端 watch,变更即推 |
| Kafka 元数据 | Kafka 用 ZK 存 broker/partition/消费组偏移等元数据(新版已逐步去 ZK 化) |
⚖️ZooKeeper vs etcd
| 维度 | ZooKeeper | etcd |
|---|---|---|
| 一致性协议 | ZAB | Raft |
| 数据接口 | 树形 ZNode + Watcher | KV + 租约 + watch(gRPC) |
| 一致性等级 | 顺序一致 | 强一致(线性izable 读可配) |
| 典型使用者 | Hadoop/HBase/Kafka(旧) | Kubernetes / CoreDNS |
| 趋势 | 生态老但稳 | 云原生新宠 |
🎯面试要点速记
定位:分布式协调服务,存元数据(小数据),不是 DB/MQ。
模型:ZNode 树,节点分持久/临时/顺序;临时节点随会话消失。
一致性:ZAB 协议(崩溃恢复 + 原子广播),顺序一致性。
Watcher:一次性监听,触发后需重注册;用于配置推送/状态感知。
选主/锁:临时顺序节点,序号最小者获锁/Master。
对比:与 etcd 同源思想,ZAB vs Raft,树形 vs KV。
必考题:"如何用 ZK 实现分布式锁?"——在锁目录下建临时顺序节点,判断自己是否序号最小;是则获锁,否则 watch 前一个节点,前一个释放(删节点)时收到通知再重试。用临时节点防止"持有者宕机不释放"导致的死锁。