文档
ZooKeeper 入门教程:分布式协调核心原理
1. 为什么需要独立的协调服务?
在分布式系统中,节点间需要就某些事情达成一致:
- 谁是 Leader?
- 配置变更了谁通知?
- 这个资源谁在使用?
与其每个服务自己实现 Paxos/Raft,不如用一个经过验证的通用协调服务——这就是 ZooKeeper 的定位。
2. ZNode 详解
ZooKeeper 数据模型类似文件系统:
/
├── config/ # 持久节点
│ ├── db_url # 数据库连接串
│ └── feature_flag # 功能开关
├── services/ # 临时节点(服务注册)
│ ├── service-a-001
│ └── service-a-002
└── locks/ # 临时顺序节点(分布式锁)
├── lock-0000001
└── lock-0000002
四种节点类型
| 类型 | 创建命令 | 生命周期 |
|---|---|---|
| PERSISTENT | create /path data |
持续到显式删除 |
| PERSISTENT_SEQUENTIAL | create -s /path data |
同上 + 自增后缀 |
| EPHEMERAL | create -e /path data |
客户端断开即删除 |
| EPHEMERAL_SEQUENTIAL | create -e -s /path data |
同上 + 自增后缀 |
3. Watcher 机制
客户端可以对 ZNode 设置 Watcher,触发一次回调:
@zk.DataWatch('/config/timeout')
def on_config_change(data, stat):
if data:
update_timeout(int(data.decode()))
注意:Watcher 是一次性的!触发后需重新注册。Kazoo 等客户端已封装此行为。
4. 经典应用场景
配置管理
/config/app/db_url = "mysql://..."
/config/app/log_level = "INFO"
所有节点 Watch /config,配置变更时实时推送。
服务发现
/services/order-service/server-001 (Ephemeral)
/services/order-service/server-002 (Ephemeral)
服务器启动创建临时节点,宕机自动删除。消费者监听 /services/order-service 子节点变化。
分布式锁
利用临时顺序节点:
- 所有请求者在
/lock/resource下创建临时顺序节点 - 序号最小的获得锁
- 释放锁时删除节点,下一个最小序号的被唤醒
5. ZAB 协议简介
ZooKeeper Atomic Broadcast:事务日志 + 原子广播
- Leader 处理写请求,转发 Proposal 给 Followers
- 半数以上 ACK → Commit
- 与 Raft 相似但不完全相同
6. 思考题
- 为什么 ZooKeeper 集群推荐奇数台?2 台可以吗?
- 临时节点和 Watcher 如何配合实现服务发现?
- ZooKeeper vs etcd 选型?什么场景该用 etcd?