1. 数据模型
Zookeeper 的数据以 目录树的形式存储,每个节点称为 ZNode。
类似文件系统的目录和文件结构,ZNode 可以有子节点(临时节点除外)。
ZNode 的特点
唯一路径标识:每个 ZNode 都有一个唯一的路径(如
/parent/child
)。节点存储内容:可以存储小量数据(建议 1 MB 以下),同时包含状态信息(版本号、元数据等)。
原子性操作:数据的读写是一次性完成的,支持完整读写,不支持部分读写。
2. 节点类型
ZNode 在创建时可以指定类型,确定之后不能修改。
Zookeeper 提供以下四种节点类型:
持久节点
节点存储的数据和元信息始终存在,适用于长期存储的配置信息。
临时节点
生命周期与客户端会话绑定。适合存储短暂存在的信息,如分布式锁或 Leader 选举中的状态。
顺序节点
自动添加递增后缀的编号,用于记录创建顺序。适合任务队列或分布式锁排队的场景。
3. ZNode 的附加特性
状态信息
每个 ZNode 除了存储数据,还包含以下状态信息:
版本号(version):数据或子节点的版本号。
元数据:创建时间戳,最近修改时间戳。
数据长度:节点存储数据的字节长度。
访问控制列表(ACL)
每个 ZNode 配备一个 ACL 列表,用于限制访问权限。
权限分为读(READ)、写(WRITE)、创建(CREATE)、删除(DELETE)和管理(ADMIN)。
4. 观察(Watcher)机制
功能
Watcher 是 Zookeeper 的核心功能,用于监听 ZNode 的数据变化或子节点变化。
当被观察的节点发生指定变化时,客户端会收到通知。
设置观察的操作
exists:观察节点是否存在。
getChildren:观察子节点的变化。
getData:观察节点数据的变化。
触发观察的操作
create:节点创建。
delete:节点删除。
setData:节点数据更新。
Watcher 特点
一次性:Watcher 在触发后即失效,需要重新设置。
轻量级:仅通知客户端节点发生变化,不提供变化的细节。
5. 使用示例
持久顺序节点示例
以下是创建持久顺序节点的示例代码:
String root = "/example";
String createdPath = zk.create(root, root.getBytes(),
Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
System.out.println("Created root node: " + createdPath);
// 创建顺序节点
for (int i = 0; i < 3; i++) {
String childPath = "/example/node";
String createdChildPath = zk.create(childPath, childPath.getBytes(),
Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT_SEQUENTIAL);
System.out.println("Created child node: " + createdChildPath);
}
zk.close();
输出示例:
Created root node: /example
Created child node: /example/node0000000000
Created child node: /example/node0000000001
Created child node: /example/node0000000002
6. 适用场景
分布式锁
使用临时顺序节点实现锁排队机制。通过观察机制检测锁释放。服务发现
使用持久节点存储服务注册信息。客户端监听节点,动态更新服务列表。配置管理
持久节点存储配置数据。通过观察机制,实时通知配置变化。Leader 选举
使用临时节点存储竞选信息。客户端监听节点变化,动态感知 Leader 状态。
总结
Zookeeper 的数据结构是树形目录模型,ZNode 是存储数据的基本单位,支持持久、临时和顺序节点类型。
通过观察机制和 ACL,Zookeeper 提供了灵活的分布式协调能力,广泛应用于分布式锁、服务发现和配置管理等场景。