bigywater.tech
ZooKeeper · 95

Curator Cache、TreeCache、NodeCache

CuratorCache 把 ZooKeeper 的一棵子树镜像到本地内存,并在变化时回调。它让读变成本地查表,但也带来「缓存可能过期」的问题。这篇量加载速度、读的收益、事件的延迟与合并,以及断网期间缓存返回什么。

826 倍
读缓存(0.14 µs)相对直读 ZooKeeper(119 µs)
150 / 200
快速连续更新 200 次时监听器收到的 NODE_CHANGED 数
旧值
断网期间缓存一直返回旧值,没有过期标记

加载与读取

实测 · 本机执行输出
  建缓存并加载完成:98 ms;缓存里的节点数 1001(含 /tree 自己)
  读一个节点:缓存 0.14 µs,直接读 ZooKeeper 119 µs(约 826 倍)

缓存要镜像整棵子树,节点更多时要关心 watch 的内存。

事件

实测 · 本机执行输出
  建 → NODE_CREATED,延迟 13.3 ms
  改 → NODE_CHANGED,延迟 6.7 ms
  删 → NODE_DELETED,延迟 3.5 ms
  快速 setData 200 次(同步连续):监听器收到 NODE_CHANGED 150 次;缓存里最终值 = v199

合并行为的原因见watch 的一次性。如果每次变更都要处理,请把变更写成顺序节点(队列)而不是改同一个节点。

断网时的缓存

实测 · 本机执行输出
  切断(代理拒绝连接)发生在 +0.0 s;ZooKeeper 里 /cfg 在 +0.3 s 被改成 v2;+6.0 s 恢复网络
    +  0.1s  STATE SUSPENDED
    +  3.1s  STATE LOST
    +  6.1s  STATE RECONNECTED
    +  6.1s  VAL v2
  缓存在整个断开期间一直返回旧值 v1;恢复后 0.1 s 看到 v2(服务端早在 0.3 s 就已经是 v2)

缓存本身没有「过期时间」。需要时请在 ConnectionStateListener 里把应用标记为「配置可能过期」。这里「断网」用 TCP 代理拒绝连接实现。

分步演示

CuratorCache
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 / ZooKeeper 3.9.6(brew 安装的 jar,用 java -cp 直接启动自己的实例,OpenJDK 17 Temurin,JVM 堆 128 MiB)/ 本机回环端口 7300+,数据在临时目录;默认 tickTime=2000;计时用 time.perf_counter,数字每次运行会有小幅抖动。Curator 5.7.1 + OpenJDK 17;读耗时是 100000 次缓存读 / 2000 次直读的平均,同机本地回环;连接中断用 TCP 代理拒绝连接,会话超时 3 s
    • 没有验证:缓存的堆内存占用、选项 SINGLE_NODE_CACHE / DO_NOT_CLEAR_ON_CLOSE 的行为、缓存与旧的 PathChildrenCache / TreeCache 的差别、数十万节点的加载
    京ICP备2026067502号-1京公网安备11010502063487号