跳转至

第三章:数据模型

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

下一章我们将学习客户端操作。