Watch 触发一次就失效,这个设计带来一个微妙的问题:从触发到重新注册之间的变化怎么办?这篇用 200 次快速写入量出来,再看 3.6 之后的持久 watch 怎么解决它。
写了 200 次(终值 200);收到通知 147 次;通过「通知后重新读取」看到的不同的值 147 个 → 中间的变化被合并了:通知次数 < 写入次数,但最后一次读到的总是最新值(version 单调)
注意:通知次数每次运行都会不同,它取决于写入速度和回调里重新注册的快慢。结论是「少于写入次数」,不是 147 这个数。
PERSISTENT 模式:3 次 set + 1 次 create 子节点 之后,CLI 收到的事件:
WatchedEvent state:SyncConnected type:None path:null zxid: -1
WatchedEvent state:SyncConnected type:NodeDataChanged path:/pw zxid: 289
WatchedEvent state:SyncConnected type:NodeDataChanged path:/pw zxid: 290
WatchedEvent state:SyncConnected type:NodeDataChanged path:/pw zxid: 291
WatchedEvent state:SyncConnected type:NodeChildrenChanged path:/pw zxid: 292
WatchedEvent state:Closed type:None path:null zxid: -1持久 watch 是 ZooKeeper 3.6 加入的功能。它不会失效,但也意味着服务端会长期持有这些 watch 的内存,用得过多的后果见第 17、18 篇。
对 /pr 的递归持久 watch,收到:
WatchedEvent state:SyncConnected type:None path:null zxid: -1
WatchedEvent state:SyncConnected type:NodeDataChanged path:/pr/a zxid: 359
WatchedEvent state:SyncConnected type:NodeCreated path:/pr/a/b zxid: 360
WatchedEvent state:SyncConnected type:NodeCreated path:/pr/c zxid: 361
WatchedEvent state:SyncConnected type:NodeDeleted path:/pr/c zxid: 362
WatchedEvent state:Closed type:None path:null zxid: -1