第三章:数据模型¶
ZNode 结构¶
层次结构¶
ZooKeeper 数据模型类似于文件系统,采用树形结构:
/
├── zookeeper (系统保留节点)
│ └── config
├── services (服务注册)
│ ├── user-service
│ │ ├── instance_0001
│ │ └── instance_0002
│ └── order-service
│ └── instance_0001
├── config (配置中心)
│ ├── database
│ │ ├── mysql
│ │ └── redis
│ └── app
└── locks (分布式锁)
└── order-lock
ZNode 属性¶
public class Stat {
long czxid; // 创建时的 zxid
long mzxid; // 最后修改的 zxid
long ctime; // 创建时间
long mtime; // 修改时间
int version; // 数据版本号
int cversion; // 子节点版本号
int aversion; // ACL 版本号
long ephemeralOwner; // 临时节点所有者会话ID
int dataLength; // 数据长度
int numChildren; // 子节点数量
long pzxid; // 子节点最后修改的 zxid
}
ZNode 类型¶
持久节点(Persistent)¶
// 创建持久节点(永久存在,直到被删除)
zk.create("/config/app",
"data".getBytes(),
ZooDefs.Ids.OPEN_ACL_UNSAFE,
CreateMode.PERSISTENT);
临时节点(Ephemeral)¶
// 创建临时节点(会话结束自动删除)
zk.create("/services/user-service/instance_0001",
"192.168.1.1:8080".getBytes(),
ZooDefs.Ids.OPEN_ACL_UNSAFE,
CreateMode.EPHEMERAL);
持久顺序节点(Persistent_Sequential)¶
// 创建持久顺序节点(自动追加序号)
String path = zk.create("/locks/order-",
"lock".getBytes(),
ZooDefs.Ids.OPEN_ACL_UNSAFE,
CreateMode.PERSISTENT_SEQUENTIAL);
// 返回: /locks/order-0000000001
临时顺序节点(Ephemeral_Sequential)¶
// 创建临时顺序节点(会话结束自动删除 + 自动追加序号)
String path = zk.create("/locks/order-",
"lock".getBytes(),
ZooDefs.Ids.OPEN_ACL_UNSAFE,
CreateMode.EPHEMERAL_SEQUENTIAL);
// 返回: /locks/order-0000000001
容器节点(Container)¶
// 创建容器节点(子节点为空时自动删除)
zk.create("/parent",
"data".getBytes(),
ZooDefs.Ids.OPEN_ACL_UNSAFE,
CreateMode.CONTAINER);
数据操作¶
创建节点¶
// 同步创建
zk.create("/config/app",
"data".getBytes(),
ZooDefs.Ids.OPEN_ACL_UNSAFE,
CreateMode.PERSISTENT);
// 异步创建
zk.create("/config/app",
"data".getBytes(),
ZooDefs.Ids.OPEN_ACL_UNSAFE,
CreateMode.PERSISTENT,
new AsyncCallback.Create2Callback() {
@Override
public void processResult(int rc, String path, Object ctx, String name, Stat stat) {
System.out.println("创建成功: " + name);
}
},
null);
读取数据¶
// 同步读取
Stat stat = new Stat();
byte[] data = zk.getData("/config/app", false, stat);
System.out.println("数据: " + new String(data));
// 异步读取
zk.getData("/config/app", false, new AsyncCallback.DataCallback() {
@Override
public void processResult(int rc, String path, Object ctx, byte[] data, Stat stat) {
System.out.println("数据: " + new String(data));
}
}, null);
更新数据¶
// 同步更新(乐观锁)
Stat stat = zk.exists("/config/app", false);
zk.setData("/config/app", "new-data".getBytes(), stat.getVersion());
// 异步更新
zk.setData("/config/app", "new-data".getBytes(), -1,
new AsyncCallback.StatCallback() {
@Override
public void processResult(int rc, String path, Object ctx, Stat stat) {
System.out.println("更新成功");
}
}, null);
删除节点¶
// 同步删除
Stat stat = zk.exists("/config/app", false);
zk.delete("/config/app", stat.getVersion());
// 异步删除
zk.delete("/config/app", -1, new AsyncCallback.VoidCallback() {
@Override
public void processResult(int rc, String path, Object ctx) {
System.out.println("删除成功");
}
}, null);
获取子节点¶
// 同步获取
List<String> children = zk.getChildren("/services", false);
for (String child : children) {
System.out.println("子节点: " + child);
}
// 异步获取
zk.getChildren("/services", false, new AsyncCallback.Children2Callback() {
@Override
public void processResult(int rc, String path, Object ctx, List<String> children, Stat stat) {
for (String child : children) {
System.out.println("子节点: " + child);
}
}
}, null);
ACL 权限控制¶
权限类型¶
// 权限类型
ZooDefs.Perms.READ // 读权限
ZooDefs.Perms.WRITE // 写权限
ZooDefs.Perms.CREATE // 创建权限
ZooDefs.Perms.DELETE // 删除权限
ZooDefs.Perms.ADMIN // 管理权限
内置 ACL¶
// 完全开放
ZooDefs.Ids.OPEN_ACL_UNSAFE
// 只读
ZooDefs.Ids.READ_ACL_UNSAFE
// 所有权限
ZooDefs.Ids.ALL_ACL_UNSAFE
// 认证用户
ZooDefs.Ids.CREATOR_ALL_ACL
自定义 ACL¶
// 创建带 ACL 的节点
List<ACL> acls = new ArrayList<>();
acls.add(new ACL(ZooDefs.Perms.ALL, new Id("auth", "user:password")));
acls.add(new ACL(ZooDefs.Perms.READ, Ids.ANYONE_ID_UNSAFE));
zk.create("/secure-node", "data".getBytes(), acls, CreateMode.PERSISTENT);
小结¶
数据模型要点:
- ZNode 结构:树形结构、节点属性
- ZNode 类型:持久、临时、顺序、容器
- 数据操作:创建、读取、更新、删除
- ACL 权限:权限类型、内置 ACL、自定义 ACL
下一章我们将学习客户端操作。