bigywater.tech
ZooKeeper · 9

顺序节点

顺序节点(SEQUENTIAL)是 ZooKeeper 实现锁、队列、选举的核心零件。它的序号到底怎么来的?删除之后会不会重用?并发创建会不会重复?这篇都量一遍,并顺手纠正一个我原先以为的说法:序号并不等于父节点的 cversion。

10 位十进制
序号格式:前缀 + 左补零的 10 位数字
不重用
删除子节点后,序号继续往后走
400 个唯一
8 线程并发创建 400 个顺序节点,序号恰好是 0..399

序号的格式

实测 · 本机执行输出
   ['/q/item-0000000000', '/q/item-0000000001', '/q/item-0000000002']

删除之后

实测 · 本机执行输出
  现在 /q 的 cversion = 3 , 子节点: ['item-0000000000', 'item-0000000001', 'item-0000000002']
  删掉 2 个之后 cversion = 5 , 子节点: ['item-0000000002']
  再创建一个顺序节点 → /q/item-0000000003  | 创建后 cversion = 6
  对照实验:/s 下 顺序 → 普通子节点 → 顺序 → 删掉普通子节点 → 顺序: ['n-0000000000', 'n-0000000002', 'n-0000000003'] | 此时 /s 的 cversion = 5

我原本以为序号等于父节点当时的 cversion(第 7 篇),实测不是:cversion 为 5 时拿到的是 3。对照实验显示普通子节点也占用序号,所以这里只下一个能被现象支持的结论:按父节点计数,每创建一个子节点加一,删除不减。准确的内部机制本文没有查源码确认。

每个父节点独立计数

实测 · 本机执行输出
  /r 下: /r/x-0000000000 | /q 下: /q/x-0000000004 | / 下: /x-0000000003

并发创建

实测 · 本机执行输出
  总数 400 | 不同序号数 400 | 最小 0 最大 399 | 恰好是 0..399: True

临时顺序节点

实测 · 本机执行输出
  创建顺序:z → w → z;得到: ['l-0000000000', 'l-0000000001', 'l-0000000002']
  /lk 的子节点排序: ['l-0000000000', 'l-0000000001', 'l-0000000002']
  w 的会话关闭后: ['l-0000000000', 'l-0000000002'] (序号不连续,w 的那个没了)

分步演示

顺序节点
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 / ZooKeeper 3.9.6(brew 安装的 jar,用 java -cp 直接启动自己的实例,OpenJDK 17 Temurin,JVM 堆 128 MiB)/ 本机回环端口 7300+,数据在临时目录;默认 tickTime=2000;计时用 time.perf_counter,数字每次运行会有小幅抖动。单机节点;并发测试是同一进程里的 8 个线程各用一个 kazoo 客户端
    • 没有验证:序号溢出(2^31 之后)、集群里经由 follower 创建时的行为、序号计数的内部实现、顺序节点用在锁与队列里的完整流程(第 79、82 篇)
    京ICP备2026067502号-1京公网安备11010502063487号