bigywater.tech
ZooKeeper · 7

ZNode 数据模型

znode 是 ZooKeeper 里唯一的数据结构。它的 stat 里 czxid、mzxid、pzxid、version、cversion、aversion 到底各自什么时候变?路径有什么限制?这篇把每种操作前后的 stat 做 diff,逐项验证。

3 个 zxid
czxid 创建 / mzxid 修改数据 / pzxid 子节点列表最后一次变化
3 个版本号
version 数据 / cversion 子节点 / aversion ACL
删子节点 cversion +1
父节点的 cversion 只增不减

stat 的字段

实测 · 本机执行输出
  czxid           = 0x2
  mzxid           = 0x2
  pzxid           = 0x2
  version         = 0
  cversion        = 0
  aversion        = 0
  numChildren     = 0
  dataLength      = 5
  ephemeralOwner  = 0x0

每种操作改变了什么

实测 · 本机执行输出
  set /p 新数据             → /p 的变化: {'mzxid': '0x2→0x3', 'version': '0→1', 'dataLength': '5→10', 'mtime': '1790816773889→1790816773896'}
  创建子节点 /p/c             → /p 的变化: {'pzxid': '0x2→0x4', 'cversion': '0→1', 'numChildren': '0→1'}
  再创建 /p/d               → /p 的变化: {'pzxid': '0x4→0x5', 'cversion': '1→2', 'numChildren': '1→2'}
  修改子节点数据 /p/c           → /p 的变化: (无变化)
  删除子节点 /p/d             → /p 的变化: {'pzxid': '0x5→0x7', 'cversion': '2→3', 'numChildren': '2→1'}
  setACL /p              → /p 的变化: {'aversion': '0→1'}
  子节点 /p/c 的 stat(它没被 /p 的操作影响): {'czxid': 4, 'mzxid': 6, 'version': 1, 'cversion': 0, 'numChildren': 0}

这个表是后面很多实验的基础:Watcher 和版本号的条件更新(set -v)都建立在这些字段上。

时间戳

实测 · 本机执行输出
  /p 的 ctime = 1790816773889、mtime = 1790816773896(毫秒);与本机时间差:21 ms(同一台机器)

路径规则

实测 · 本机执行输出
  create '/ok'            → Created /ok
  create '/中文'            → Created /中文
  create '/a/'            → Path must not end with / character
  create '//a'            → Invalid path string "//a" caused by empty node name specified @1
  create '/a//b'          → Invalid path string "/a//b" caused by empty node name specified @3
  create '/.'             → Invalid path string "/." caused by relative paths not allowed @1
  create '/a/./b'         → Invalid path string "/a/./b" caused by relative paths not allowed @3
  create '/a/../b'        → Invalid path string "/a/../b" caused by relative paths not allowed @4
  create 'noslash'        → Path must start with / character
  create '/zookeeper/x'   → Created /zookeeper/x
  create '/a/b'           → Node does not exist: /a/b

路径校验发生在 Java 客户端里(请求到达服务端之前)。kazoo 这类客户端会先帮你规范化路径(比如去掉末尾的斜杠),所以这一节用官方的 Java 客户端测;不同语言的客户端对不规范路径的处理可能不同。

分步演示

znode 的 stat
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 / ZooKeeper 3.9.6(brew 安装的 jar,用 java -cp 直接启动自己的实例,OpenJDK 17 Temurin,JVM 堆 128 MiB)/ 本机回环端口 7300+,数据在临时目录;默认 tickTime=2000;计时用 time.perf_counter,数字每次运行会有小幅抖动。stat 取自 kazoo 的 get();路径用官方 ZooKeeperMain 创建
    • 没有验证:ephemeralOwner 的含义与临时节点(第 8 篇)、ACL 的具体语义(第 71 篇)、节点数量与路径深度的上限、数据为空与不存在的区别、ctime 的时区与时钟漂移(多机)
    京ICP备2026067502号-1京公网安备11010502063487号