ZooKeeper
简介
Apache ZooKeeper 是分布式协调服务,用于维护配置信息、命名服务、分布式同步和组服务。它是许多分布式系统的核心组件。
数据模型
ZooKeeper 的数据模型是层次化的命名空间,类似文件系统:
/
├── /dubbo
│ ├── /com.example.UserService
│ │ ├── /providers
│ │ │ ├── /dubbo://192.168.1.1:20880
│ │ │ └── /dubbo://192.168.1.2:20880
│ │ └── /consumers
│ └── /configurators
├── /config
│ ├── /database.url
│ └── /redis.host
└── /lock节点类型
- 持久节点:创建后一直存在,除非主动删除
- 临时节点:创建它的会话结束后自动删除
- 顺序节点:创建时自动在名称后追加递增序号
核心功能
服务发现(与 Dubbo 集成)
java
// 服务提供者注册
ZooKeeper zk = new ZooKeeper("localhost:2181", 3000, null);
String path = "/dubbo/service/providers/dubbo://192.168.1.1:20880";
zk.create(path, new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
// 服务消费者监听
zk.getChildren("/dubbo/service/providers", event -> {
// 服务列表变化时重新获取
List<String> providers = zk.getChildren("/dubbo/service/providers", false);
});分布式锁
java
public class DistributedLock {
private ZooKeeper zk;
private String lockPath = "/locks/lock";
public void lock() throws Exception {
String node = zk.create(lockPath, null,
ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
// 获取所有子节点并排序,检查自己是否是最小节点
List<String> children = zk.getChildren("/locks", false);
Collections.sort(children);
String currentNode = node.substring(node.lastIndexOf("/") + 1);
if (!currentNode.equals(children.get(0))) {
// 监听前一个节点
String prevNode = children.get(children.indexOf(currentNode) - 1);
CountDownLatch latch = new CountDownLatch(1);
zk.exists("/locks/" + prevNode, event -> latch.countDown());
latch.await();
}
}
public void unlock() throws Exception {
zk.delete(lockPath, -1);
}
}集群角色
| 角色 | 职责 |
|---|---|
| Leader | 处理写请求,协调集群 |
| Follower | 处理读请求,参与选举 |
| Observer | 处理读请求,不参与选举 |
ZAB 协议:ZooKeeper 使用 ZAB(ZooKeeper Atomic Broadcast)协议保证数据一致性。