bigywater.tech
ZooKeeper · 15

Watcher 监听机制

Watcher 是 ZooKeeper 最有特色的功能,也是最容易理解错的:谁能触发它?事件里有什么?触发后还有效吗?这篇做一个触发矩阵,每一种「注册 + 操作」组合都真实执行一遍。

3 种 watch
数据(get)、存在(exists)、子节点(get_children)
事件不带数据
只有 type / state / path,要再读一次
一次性
触发后失效,连续写 3 次只收到 1 个事件

触发矩阵

实测 · 本机执行输出
  get(/m/a, watch) 然后 set /m/a                 → [('data', 'CHANGED', '/m/a')]
  get(/m/a2, watch) 然后 delete /m/a2            → [('data', 'DELETED', '/m/a2')]
  exists(/m/b, watch) 然后 create /m/b           → [('exists', 'CREATED', '/m/b')]
  exists(/m/b, watch) 然后 set /m/b              → [('exists', 'CHANGED', '/m/b')]
  get_children(/m/p1, watch) 然后 create /m/p1/c → [('child', 'CHILD', '/m/p1')]
  get_children(/m/p1, watch) 然后 set /m/p1/c    → 没有事件
  get_children(/m/p2, watch) 然后 delete /m/p2/c → [('child', 'CHILD', '/m/p2')]
  get_children(/m/p3, watch) 然后 delete /m/p3 本身 → [('child', 'DELETED', '/m/p3')]
  get(/m/q, watch) 然后 create /m/q/c(父节点数据 watch) → 没有事件

kazoo 里 watch 的事件类型叫 CHANGED / DELETED / CREATED / CHILD,对应 Java 客户端的 NodeDataChanged / NodeDeleted / NodeCreated / NodeChildrenChanged。

事件里有什么

实测 · 本机执行输出
  事件对象的字段: {'type': 'CHANGED', 'state': 'CONNECTED', 'path': '/n'} | 有数据字段吗: False
  事件之后再 get(/n) 拿到: b'v2'

一次性触发

实测 · 本机执行输出
  连续 3 次 set 之后收到的事件数: 1 ['CHANGED']

分步演示

Watcher
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 / ZooKeeper 3.9.6(brew 安装的 jar,用 java -cp 直接启动自己的实例,OpenJDK 17 Temurin,JVM 堆 128 MiB)/ 本机回环端口 7300+,数据在临时目录;默认 tickTime=2000;计时用 time.perf_counter,数字每次运行会有小幅抖动。单机;两个 kazoo 客户端:一个注册 watch,一个做修改;每种组合使用独立路径
    • 没有验证:持久 watch(第 16 篇)、重连之后 watch 是否保留(客户端库行为)、同一路径多次注册的去重(第 18 篇)、顺序保证(事件与读取之间的先后)
    京ICP备2026067502号-1京公网安备11010502063487号