欢迎光临
我们一直在努力

ZooKeeper ZNode结构详解:从数据模型到核心属性

ZooKeeper ZNode结构详解:从数据模型到核心属性

    • 一、ZNode概述
      • 1.1 什么是ZNode?
      • 1.2 ZNode的核心特性
    • 二、ZNode的物理结构
      • 2.1 ZNode的组成部分
      • 2.2 源码中的ZNode表示
      • 2.3 内存数据结构
    • 三、ZNode的逻辑结构
      • 3.1 路径命名规则
      • 3.2 节点层级关系
    • 四、ZNode的类型
      • 4.1 四种基本类型
      • 4.2 顺序节点的命名规则
      • 4.3 节点类型判断
    • 五、ZNode的Stat属性详解
      • 5.1 Stat属性完整列表
      • 5.2 通过命令行查看Stat
      • 5.3 各个字段详细说明
      • 5.4 版本号的乐观锁应用
    • 六、ACL属性
      • 6.1 ACL组成
      • 6.2 权限类型
      • 6.3 常见的Scheme
    • 七、ZNode的操作
      • 7.1 核心操作命令
      • 7.2 创建节点示例
    • 八、总结
      • 8.1 ZNode结构要点
      • 8.2 Stat属性速查表
      • 8.3 一句话总结

🌺The Begin🌺点点关注,收藏不迷路🌺

摘要:ZNode是ZooKeeper中最基础也是最重要的概念,理解ZNode的结构和属性是掌握ZooKeeper的关键。本文将深入剖析ZNode的物理结构、逻辑组织、节点类型以及详细的Stat属性,通过流程图和源码分析,帮助读者全面理解这个分布式协调的核心数据模型。

一、ZNode概述

1.1 什么是ZNode?

ZNode(ZooKeeper Node)是ZooKeeper中数据模型的基本单元,类似于文件系统中的文件或目录。ZooKeeper使用一种树形结构的命名空间来组织这些ZNode。

#mermaid-svg-9ahjum3HA9ZXCVrs{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-9ahjum3HA9ZXCVrs .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-9ahjum3HA9ZXCVrs .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-9ahjum3HA9ZXCVrs .error-icon{fill:#552222;}#mermaid-svg-9ahjum3HA9ZXCVrs .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-9ahjum3HA9ZXCVrs .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-9ahjum3HA9ZXCVrs .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-9ahjum3HA9ZXCVrs .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-9ahjum3HA9ZXCVrs .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-9ahjum3HA9ZXCVrs .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-9ahjum3HA9ZXCVrs .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-9ahjum3HA9ZXCVrs .marker{fill:#333333;stroke:#333333;}#mermaid-svg-9ahjum3HA9ZXCVrs .marker.cross{stroke:#333333;}#mermaid-svg-9ahjum3HA9ZXCVrs svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-9ahjum3HA9ZXCVrs p{margin:0;}#mermaid-svg-9ahjum3HA9ZXCVrs .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-9ahjum3HA9ZXCVrs .cluster-label text{fill:#333;}#mermaid-svg-9ahjum3HA9ZXCVrs .cluster-label span{color:#333;}#mermaid-svg-9ahjum3HA9ZXCVrs .cluster-label span p{background-color:transparent;}#mermaid-svg-9ahjum3HA9ZXCVrs .label text,#mermaid-svg-9ahjum3HA9ZXCVrs span{fill:#333;color:#333;}#mermaid-svg-9ahjum3HA9ZXCVrs .node rect,#mermaid-svg-9ahjum3HA9ZXCVrs .node circle,#mermaid-svg-9ahjum3HA9ZXCVrs .node ellipse,#mermaid-svg-9ahjum3HA9ZXCVrs .node polygon,#mermaid-svg-9ahjum3HA9ZXCVrs .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-9ahjum3HA9ZXCVrs .rough-node .label text,#mermaid-svg-9ahjum3HA9ZXCVrs .node .label text,#mermaid-svg-9ahjum3HA9ZXCVrs .image-shape .label,#mermaid-svg-9ahjum3HA9ZXCVrs .icon-shape .label{text-anchor:middle;}#mermaid-svg-9ahjum3HA9ZXCVrs .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-9ahjum3HA9ZXCVrs .rough-node .label,#mermaid-svg-9ahjum3HA9ZXCVrs .node .label,#mermaid-svg-9ahjum3HA9ZXCVrs .image-shape .label,#mermaid-svg-9ahjum3HA9ZXCVrs .icon-shape .label{text-align:center;}#mermaid-svg-9ahjum3HA9ZXCVrs .node.clickable{cursor:pointer;}#mermaid-svg-9ahjum3HA9ZXCVrs .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-9ahjum3HA9ZXCVrs .arrowheadPath{fill:#333333;}#mermaid-svg-9ahjum3HA9ZXCVrs .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-9ahjum3HA9ZXCVrs .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-9ahjum3HA9ZXCVrs .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-9ahjum3HA9ZXCVrs .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-9ahjum3HA9ZXCVrs .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-9ahjum3HA9ZXCVrs .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-9ahjum3HA9ZXCVrs .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-9ahjum3HA9ZXCVrs .cluster text{fill:#333;}#mermaid-svg-9ahjum3HA9ZXCVrs .cluster span{color:#333;}#mermaid-svg-9ahjum3HA9ZXCVrs div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-9ahjum3HA9ZXCVrs .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-9ahjum3HA9ZXCVrs rect.text{fill:none;stroke-width:0;}#mermaid-svg-9ahjum3HA9ZXCVrs .icon-shape,#mermaid-svg-9ahjum3HA9ZXCVrs .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-9ahjum3HA9ZXCVrs .icon-shape p,#mermaid-svg-9ahjum3HA9ZXCVrs .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-9ahjum3HA9ZXCVrs .icon-shape rect,#mermaid-svg-9ahjum3HA9ZXCVrs .image-shape rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-9ahjum3HA9ZXCVrs .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-9ahjum3HA9ZXCVrs .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-9ahjum3HA9ZXCVrs :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

/ (根节点)

/app

/services

/config

/app/config

/app/status

/services/gateway

/services/user

/config/database

/config/redis

1.2 ZNode的核心特性

特性说明
路径标识 每个ZNode通过绝对路径唯一标识,如 /app/config
数据存储 可存储数据,默认最大1MB,建议<1KB
原子操作 读操作获取完整数据,写操作替换全部数据
兼具文件/目录特性 既可以存储数据(像文件),也可以有子节点(像目录)
节点类型 持久/临时/顺序/容器四种类型
版本控制 每个节点都有数据版本、子节点版本、ACL版本

二、ZNode的物理结构

2.1 ZNode的组成部分

每个ZNode由三个核心部分组成:

#mermaid-svg-RDJCRFOTQK0qn8Qn{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-RDJCRFOTQK0qn8Qn .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-RDJCRFOTQK0qn8Qn .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-RDJCRFOTQK0qn8Qn .error-icon{fill:#552222;}#mermaid-svg-RDJCRFOTQK0qn8Qn .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-RDJCRFOTQK0qn8Qn .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-RDJCRFOTQK0qn8Qn .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-RDJCRFOTQK0qn8Qn .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-RDJCRFOTQK0qn8Qn .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-RDJCRFOTQK0qn8Qn .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-RDJCRFOTQK0qn8Qn .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-RDJCRFOTQK0qn8Qn .marker{fill:#333333;stroke:#333333;}#mermaid-svg-RDJCRFOTQK0qn8Qn .marker.cross{stroke:#333333;}#mermaid-svg-RDJCRFOTQK0qn8Qn svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-RDJCRFOTQK0qn8Qn p{margin:0;}#mermaid-svg-RDJCRFOTQK0qn8Qn .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-RDJCRFOTQK0qn8Qn .cluster-label text{fill:#333;}#mermaid-svg-RDJCRFOTQK0qn8Qn .cluster-label span{color:#333;}#mermaid-svg-RDJCRFOTQK0qn8Qn .cluster-label span p{background-color:transparent;}#mermaid-svg-RDJCRFOTQK0qn8Qn .label text,#mermaid-svg-RDJCRFOTQK0qn8Qn span{fill:#333;color:#333;}#mermaid-svg-RDJCRFOTQK0qn8Qn .node rect,#mermaid-svg-RDJCRFOTQK0qn8Qn .node circle,#mermaid-svg-RDJCRFOTQK0qn8Qn .node ellipse,#mermaid-svg-RDJCRFOTQK0qn8Qn .node polygon,#mermaid-svg-RDJCRFOTQK0qn8Qn .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-RDJCRFOTQK0qn8Qn .rough-node .label text,#mermaid-svg-RDJCRFOTQK0qn8Qn .node .label text,#mermaid-svg-RDJCRFOTQK0qn8Qn .image-shape .label,#mermaid-svg-RDJCRFOTQK0qn8Qn .icon-shape .label{text-anchor:middle;}#mermaid-svg-RDJCRFOTQK0qn8Qn .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-RDJCRFOTQK0qn8Qn .rough-node .label,#mermaid-svg-RDJCRFOTQK0qn8Qn .node .label,#mermaid-svg-RDJCRFOTQK0qn8Qn .image-shape .label,#mermaid-svg-RDJCRFOTQK0qn8Qn .icon-shape .label{text-align:center;}#mermaid-svg-RDJCRFOTQK0qn8Qn .node.clickable{cursor:pointer;}#mermaid-svg-RDJCRFOTQK0qn8Qn .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-RDJCRFOTQK0qn8Qn .arrowheadPath{fill:#333333;}#mermaid-svg-RDJCRFOTQK0qn8Qn .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-RDJCRFOTQK0qn8Qn .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-RDJCRFOTQK0qn8Qn .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-RDJCRFOTQK0qn8Qn .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-RDJCRFOTQK0qn8Qn .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-RDJCRFOTQK0qn8Qn .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-RDJCRFOTQK0qn8Qn .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-RDJCRFOTQK0qn8Qn .cluster text{fill:#333;}#mermaid-svg-RDJCRFOTQK0qn8Qn .cluster span{color:#333;}#mermaid-svg-RDJCRFOTQK0qn8Qn div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-RDJCRFOTQK0qn8Qn .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-RDJCRFOTQK0qn8Qn rect.text{fill:none;stroke-width:0;}#mermaid-svg-RDJCRFOTQK0qn8Qn .icon-shape,#mermaid-svg-RDJCRFOTQK0qn8Qn .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-RDJCRFOTQK0qn8Qn .icon-shape p,#mermaid-svg-RDJCRFOTQK0qn8Qn .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-RDJCRFOTQK0qn8Qn .icon-shape rect,#mermaid-svg-RDJCRFOTQK0qn8Qn .image-shape rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-RDJCRFOTQK0qn8Qn .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-RDJCRFOTQK0qn8Qn .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-RDJCRFOTQK0qn8Qn :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

ZNode结构

ZNode

data: 业务数据

stat: 状态信息

acl: 访问控制列表

children: 子节点列表

组成部分说明存储内容
data 业务数据 字节数组,可存储任何序列化数据
stat 状态信息 版本号、时间戳、事务ID等元数据
acl 访问控制 定义谁可以对该节点执行什么操作
children 子节点列表 当前节点的直接子节点路径

2.2 源码中的ZNode表示

在ZooKeeper源码中,ZNode由DataNode类表示:

// ZooKeeper源码:org.apache.zookeeper.server.DataNode
public class DataNode {
// 节点数据(字节数组)
volatile byte[] data;

// ACL权限(引用计数方式)
Long acl;

// 节点状态(持久化信息)
private volatile StatPersisted stat;

// 子节点集合(路径名 -> 不包含完整路径)
private Set<String> children = new HashSet<>();

// 父节点引用(用于快速路径查找)
private DataNode parent;

// 构造函数
public DataNode() {
this.data = new byte[0];
this.stat = new StatPersisted();
this.children = new HashSet<>();
}

// 添加子节点
public synchronized boolean addChild(String child) {
return children.add(child);
}

// 删除子节点
public synchronized boolean removeChild(String child) {
return children.remove(child);
}

// 获取子节点列表(拷贝)
public synchronized Set<String> getChildren() {
return new HashSet<>(children);
}

// 复制节点状态
public void copyStat(Stat to) {
stat.copy(to);
}
}

2.3 内存数据结构

ZooKeeper将所有ZNode存储在内存中,使用ConcurrentHashMap进行管理:

// DataTree类中的节点存储
public class DataTree {
// 路径 -> DataNode 的映射
private final ConcurrentHashMap<String, DataNode> nodes =
new ConcurrentHashMap<>();

// 临时节点索引:会话ID -> 该会话创建的所有临时节点
private final ConcurrentHashMap<Long, HashSet<String>> ephemerals =
new ConcurrentHashMap<>();

// 根节点
private static final String rootZookeeper = "/";

// 获取节点
public DataNode getNode(String path) {
return nodes.get(path);
}

// 创建节点
public void createNode(String path, byte[] data, List<ACL> acl,
long ephemeralOwner, int parentCVersion,
long zxid, long time) {
// … 创建逻辑
}
}

三、ZNode的逻辑结构

3.1 路径命名规则

ZNode的路径必须遵循以下规则:

规则正确示例错误示例
必须以/开头 /app/config app/config
不能有连续/ /app/config /app//config
不能以.开头 /app/config /app/.config
区分大小写 /App和/app不同
长度不限 建议不要太长

3.2 节点层级关系

#mermaid-svg-Jj9HsuTmFhSv4Od5{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-Jj9HsuTmFhSv4Od5 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-Jj9HsuTmFhSv4Od5 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-Jj9HsuTmFhSv4Od5 .error-icon{fill:#552222;}#mermaid-svg-Jj9HsuTmFhSv4Od5 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-Jj9HsuTmFhSv4Od5 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-Jj9HsuTmFhSv4Od5 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-Jj9HsuTmFhSv4Od5 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-Jj9HsuTmFhSv4Od5 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-Jj9HsuTmFhSv4Od5 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-Jj9HsuTmFhSv4Od5 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-Jj9HsuTmFhSv4Od5 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-Jj9HsuTmFhSv4Od5 .marker.cross{stroke:#333333;}#mermaid-svg-Jj9HsuTmFhSv4Od5 svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-Jj9HsuTmFhSv4Od5 p{margin:0;}#mermaid-svg-Jj9HsuTmFhSv4Od5 .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-Jj9HsuTmFhSv4Od5 .cluster-label text{fill:#333;}#mermaid-svg-Jj9HsuTmFhSv4Od5 .cluster-label span{color:#333;}#mermaid-svg-Jj9HsuTmFhSv4Od5 .cluster-label span p{background-color:transparent;}#mermaid-svg-Jj9HsuTmFhSv4Od5 .label text,#mermaid-svg-Jj9HsuTmFhSv4Od5 span{fill:#333;color:#333;}#mermaid-svg-Jj9HsuTmFhSv4Od5 .node rect,#mermaid-svg-Jj9HsuTmFhSv4Od5 .node circle,#mermaid-svg-Jj9HsuTmFhSv4Od5 .node ellipse,#mermaid-svg-Jj9HsuTmFhSv4Od5 .node polygon,#mermaid-svg-Jj9HsuTmFhSv4Od5 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-Jj9HsuTmFhSv4Od5 .rough-node .label text,#mermaid-svg-Jj9HsuTmFhSv4Od5 .node .label text,#mermaid-svg-Jj9HsuTmFhSv4Od5 .image-shape .label,#mermaid-svg-Jj9HsuTmFhSv4Od5 .icon-shape .label{text-anchor:middle;}#mermaid-svg-Jj9HsuTmFhSv4Od5 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-Jj9HsuTmFhSv4Od5 .rough-node .label,#mermaid-svg-Jj9HsuTmFhSv4Od5 .node .label,#mermaid-svg-Jj9HsuTmFhSv4Od5 .image-shape .label,#mermaid-svg-Jj9HsuTmFhSv4Od5 .icon-shape .label{text-align:center;}#mermaid-svg-Jj9HsuTmFhSv4Od5 .node.clickable{cursor:pointer;}#mermaid-svg-Jj9HsuTmFhSv4Od5 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-Jj9HsuTmFhSv4Od5 .arrowheadPath{fill:#333333;}#mermaid-svg-Jj9HsuTmFhSv4Od5 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-Jj9HsuTmFhSv4Od5 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-Jj9HsuTmFhSv4Od5 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Jj9HsuTmFhSv4Od5 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-Jj9HsuTmFhSv4Od5 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Jj9HsuTmFhSv4Od5 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-Jj9HsuTmFhSv4Od5 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-Jj9HsuTmFhSv4Od5 .cluster text{fill:#333;}#mermaid-svg-Jj9HsuTmFhSv4Od5 .cluster span{color:#333;}#mermaid-svg-Jj9HsuTmFhSv4Od5 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-Jj9HsuTmFhSv4Od5 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-Jj9HsuTmFhSv4Od5 rect.text{fill:none;stroke-width:0;}#mermaid-svg-Jj9HsuTmFhSv4Od5 .icon-shape,#mermaid-svg-Jj9HsuTmFhSv4Od5 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Jj9HsuTmFhSv4Od5 .icon-shape p,#mermaid-svg-Jj9HsuTmFhSv4Od5 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-Jj9HsuTmFhSv4Od5 .icon-shape rect,#mermaid-svg-Jj9HsuTmFhSv4Od5 .image-shape rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Jj9HsuTmFhSv4Od5 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-Jj9HsuTmFhSv4Od5 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-Jj9HsuTmFhSv4Od5 :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

ZooKeeper ZNode层级树

三级节点

二级节点

一级节点

根节点

/services/api/instance-001服务实例

/ (根节点)持久节点

/app应用根节点

/services服务根节点

/app/config应用配置

/app/status应用状态

/services/apiAPI服务

/services/user用户服务

层级特性:

  • 根节点:只有一个根节点 /
  • 父节点:必须先存在才能创建子节点
  • 子节点:可以有多层嵌套
  • 路径深度:理论上无限制,但建议不要太深

四、ZNode的类型

ZNode在创建时确定类型,之后不可更改。

4.1 四种基本类型

类型创建参数生命周期是否有子节点典型应用
持久节点 PERSISTENT 直到显式删除 可以 配置信息、元数据
临时节点 EPHEMERAL 会话结束自动删除 不能有子节点 服务注册、心跳检测
持久顺序节点 PERSISTENT_SEQUENTIAL 持久存在,带递增序号 可以 任务队列、事件顺序
临时顺序节点 EPHEMERAL_SEQUENTIAL 会话结束自动删除,带序号 不能有子节点 分布式锁、Leader选举

4.2 顺序节点的命名规则

# 创建顺序节点
[zk: localhost:2181(CONNECTED) 0] create -s /task/task- "data"
Created /task/task-0000000001

[zk: localhost:2181(CONNECTED) 1] create -s /task/task- "data"
Created /task/task-0000000002

# 命名格式:指定路径 + 10位十进制数
# /task/task-0000000001
# /task/task-0000000002
# 序号从1开始,自动递增

4.3 节点类型判断

通过ephemeralOwner字段判断节点类型:

# 创建持久节点
[zk: localhost:2181(CONNECTED) 0] create /persistent "data"
Created /persistent

[zk: localhost:2181(CONNECTED) 1] stat /persistent | grep ephemeralOwner
ephemeralOwner = 0x0 # 0表示持久节点

# 创建临时节点
[zk: localhost:2181(CONNECTED) 2] create -e /ephemeral "temp"
Created /ephemeral

[zk: localhost:2181(CONNECTED) 3] stat /ephemeral | grep ephemeralOwner
ephemeralOwner = 0x100001d6d2d0003 # 非0表示临时节点,值为会话ID

五、ZNode的Stat属性详解

Stat属性记录了ZNode的所有状态信息,是理解ZNode行为的关键。

5.1 Stat属性完整列表

// ZooKeeper源码:org.apache.zookeeper.data.Stat
public class Stat {
// 创建节点的事务ID
private long czxid;

// 最后修改节点的事务ID
private long mzxid;

// 最后修改子节点的事务ID
private long pzxid;

// 创建时间(毫秒)
private long ctime;

// 最后修改时间(毫秒)
private long mtime;

// 数据版本号(每修改一次+1)
private int version;

// 子节点版本号
private int cversion;

// ACL版本号
private int aversion;

// 临时节点所有者会话ID(持久节点为0)
private long ephemeralOwner;

// 数据长度(字节)
private int dataLength;

// 子节点数量
private int numChildren;
}

5.2 通过命令行查看Stat

[zk: localhost:2181(CONNECTED) 0] stat /config

# 输出示例及解释:
cZxid = 0x100000002 # 创建时的事务ID
ctime = Thu Jan 01 08:00:00 CST 1970 # 创建时间
mZxid = 0x100000005 # 最后修改的事务ID
mtime = Thu Jan 01 08:00:02 CST 1970 # 最后修改时间
pZxid = 0x100000008 # 子节点最后修改的事务ID
cversion = 3 # 子节点版本号(已修改3次)
dataVersion = 2 # 数据版本号(已修改2次)
aclVersion = 0 # ACL版本号(未修改过)
ephemeralOwner = 0x0 # 临时节点所有者(0表示持久节点)
dataLength = 42 # 数据长度42字节
numChildren = 3 # 有3个子节点

5.3 各个字段详细说明

字段名称说明更新时机应用场景
czxid 创建事务ID 创建节点的事务ID 节点创建时 确定节点创建顺序
ctime 创建时间 节点创建的时间戳 节点创建时 监控节点存活时间
mzxid 修改事务ID 最后修改节点的事务ID 数据变更时 确定数据修改顺序
mtime 修改时间 最后修改的时间戳 数据变更时 监控数据变更频率
pzxid 子节点事务ID 最后修改子节点列表的事务ID 子节点新增/删除时 监控子节点变化
dataVersion 数据版本号 数据修改次数 每次set操作+1 乐观锁实现并发控制
cversion 子节点版本号 子节点列表修改次数 子节点新增/删除+1 监控子节点变化
aversion ACL版本号 ACL修改次数 每次setAcl操作+1 权限变更跟踪
ephemeralOwner 临时节点所有者 创建节点的会话ID 节点创建时 判断节点类型,定位所有者
dataLength 数据长度 数据字节数 数据变更时 监控数据大小,防止超限
numChildren 子节点数量 直接子节点个数 子节点变更时 监控节点负载

5.4 版本号的乐观锁应用

// 使用dataVersion实现乐观锁
public boolean updateWithVersion(String path, String newData) throws Exception {
while (true) {
// 1. 获取当前数据和版本号
Stat stat = new Stat();
byte[] data = zk.getData(path, false, stat);
int currentVersion = stat.getVersion();

// 2. 业务处理
String processed = processData(new String(data), newData);

try {
// 3. 使用版本号更新
zk.setData(path, processed.getBytes(), currentVersion);
return true; // 更新成功
} catch (KeeperException.BadVersionException e) {
// 4. 版本冲突,重试
System.out.println("版本冲突,重试中…");
continue;
}
}
}

六、ACL属性

ACL(Access Control List)定义了谁可以对该节点执行什么操作。

6.1 ACL组成

#mermaid-svg-jZCx0JM1pxOKtPX5{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-jZCx0JM1pxOKtPX5 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-jZCx0JM1pxOKtPX5 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-jZCx0JM1pxOKtPX5 .error-icon{fill:#552222;}#mermaid-svg-jZCx0JM1pxOKtPX5 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-jZCx0JM1pxOKtPX5 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-jZCx0JM1pxOKtPX5 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-jZCx0JM1pxOKtPX5 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-jZCx0JM1pxOKtPX5 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-jZCx0JM1pxOKtPX5 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-jZCx0JM1pxOKtPX5 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-jZCx0JM1pxOKtPX5 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-jZCx0JM1pxOKtPX5 .marker.cross{stroke:#333333;}#mermaid-svg-jZCx0JM1pxOKtPX5 svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-jZCx0JM1pxOKtPX5 p{margin:0;}#mermaid-svg-jZCx0JM1pxOKtPX5 .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-jZCx0JM1pxOKtPX5 .cluster-label text{fill:#333;}#mermaid-svg-jZCx0JM1pxOKtPX5 .cluster-label span{color:#333;}#mermaid-svg-jZCx0JM1pxOKtPX5 .cluster-label span p{background-color:transparent;}#mermaid-svg-jZCx0JM1pxOKtPX5 .label text,#mermaid-svg-jZCx0JM1pxOKtPX5 span{fill:#333;color:#333;}#mermaid-svg-jZCx0JM1pxOKtPX5 .node rect,#mermaid-svg-jZCx0JM1pxOKtPX5 .node circle,#mermaid-svg-jZCx0JM1pxOKtPX5 .node ellipse,#mermaid-svg-jZCx0JM1pxOKtPX5 .node polygon,#mermaid-svg-jZCx0JM1pxOKtPX5 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-jZCx0JM1pxOKtPX5 .rough-node .label text,#mermaid-svg-jZCx0JM1pxOKtPX5 .node .label text,#mermaid-svg-jZCx0JM1pxOKtPX5 .image-shape .label,#mermaid-svg-jZCx0JM1pxOKtPX5 .icon-shape .label{text-anchor:middle;}#mermaid-svg-jZCx0JM1pxOKtPX5 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-jZCx0JM1pxOKtPX5 .rough-node .label,#mermaid-svg-jZCx0JM1pxOKtPX5 .node .label,#mermaid-svg-jZCx0JM1pxOKtPX5 .image-shape .label,#mermaid-svg-jZCx0JM1pxOKtPX5 .icon-shape .label{text-align:center;}#mermaid-svg-jZCx0JM1pxOKtPX5 .node.clickable{cursor:pointer;}#mermaid-svg-jZCx0JM1pxOKtPX5 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-jZCx0JM1pxOKtPX5 .arrowheadPath{fill:#333333;}#mermaid-svg-jZCx0JM1pxOKtPX5 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-jZCx0JM1pxOKtPX5 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-jZCx0JM1pxOKtPX5 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-jZCx0JM1pxOKtPX5 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-jZCx0JM1pxOKtPX5 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-jZCx0JM1pxOKtPX5 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-jZCx0JM1pxOKtPX5 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-jZCx0JM1pxOKtPX5 .cluster text{fill:#333;}#mermaid-svg-jZCx0JM1pxOKtPX5 .cluster span{color:#333;}#mermaid-svg-jZCx0JM1pxOKtPX5 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-jZCx0JM1pxOKtPX5 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-jZCx0JM1pxOKtPX5 rect.text{fill:none;stroke-width:0;}#mermaid-svg-jZCx0JM1pxOKtPX5 .icon-shape,#mermaid-svg-jZCx0JM1pxOKtPX5 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-jZCx0JM1pxOKtPX5 .icon-shape p,#mermaid-svg-jZCx0JM1pxOKtPX5 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-jZCx0JM1pxOKtPX5 .icon-shape rect,#mermaid-svg-jZCx0JM1pxOKtPX5 .image-shape rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-jZCx0JM1pxOKtPX5 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-jZCx0JM1pxOKtPX5 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-jZCx0JM1pxOKtPX5 :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

ACL结构

ACL

scheme: 授权方案

id: 授权ID

perms: 权限位

6.2 权限类型

权限缩写数字表示说明
CREATE c 1 允许创建子节点
DELETE d 2 允许删除子节点
READ r 4 允许读取节点数据
WRITE w 8 允许修改节点数据
ADMIN a 16 允许设置ACL

6.3 常见的Scheme

Scheme说明示例
world 全世界 world:anyone:r
auth 已认证用户 auth:user:cdrwa
digest 用户名密码认证 digest:user:password:cdrwa
ip IP地址限制 ip:192.168.1.0/24:r

七、ZNode的操作

7.1 核心操作命令

命令语法作用
create create [-s] [-e] path data 创建节点
delete delete path [version] 删除节点
set set path data [version] 设置节点数据
get get path [watch] 获取节点数据+状态
stat stat path [watch] 获取节点状态
ls ls path [watch] 列出子节点

7.2 创建节点示例

# 创建持久节点
create /config "db-config"

# 创建临时节点
create -e /temp "temporary"

# 创建顺序节点
create -s /seq "sequential"

# 创建临时顺序节点
create -e -s /ephemeral-seq "tmp-seq"

八、总结

8.1 ZNode结构要点

  • 物理结构:DataNode包含data、stat、acl、children四部分,存储在内存的ConcurrentHashMap中
  • 逻辑结构:树形命名空间,路径唯一标识,父节点必须先存在
  • 节点类型:持久/临时/顺序四种类型,创建后不可更改
  • Stat属性:包含11个字段,记录节点完整生命周期
  • 版本控制:dataVersion/cversion/aversion实现乐观锁
  • ACL权限:控制节点访问权限,保障数据安全
  • 8.2 Stat属性速查表

    字段用途检查命令
    dataVersion 乐观锁并发控制 stat path | grep dataVersion
    ephemeralOwner 判断节点类型 stat path | grep ephemeralOwner
    numChildren 监控节点负载 stat path | grep numChildren
    dataLength 监控数据大小 stat path | grep dataLength
    ctime/mtime 监控节点存活 stat path | grep time

    8.3 一句话总结

    ZNode是ZooKeeper中集数据存储、状态管理、权限控制于一体的基础单元,其精妙的结构设计使得ZooKeeper能够在保证强一致性的同时,高效地管理分布式系统中的元数据和协调状态。

    在这里插入图片描述

    🌺The End🌺点点关注,收藏不迷路🌺

    赞(0)
    未经允许不得转载:171主机测评 » ZooKeeper ZNode结构详解:从数据模型到核心属性
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址