Zookeeper 从入门到入土③:Watcher
概述: 为一个节点注册监听器,在节点状态发生改变时,会给客户端发送消息。
1. 特性
- 一次性: watcher 触发后立即销毁。
- 轻量级: watch 是轻量级的,其实就是本地 JVM 的 Callback,服务器端只是存了是否有设置了 watcher 的布尔类型
- 可见性: Watch 被触发的同时再次读取数据,客户端会得到 Watch 消息再看到更新后的数据。
- 可能会丢失: 对于一个未创建的 znode 的 exist watch,如果在客户端断开连接期间被创建了,并且随后在客户端连接上之前又删除了,这种情况下,这个 Watch 事件可能会被丢失。
2. 设置 watcher
只有 stat、get、ls 才能设置 watcher
3. 事件类型
NodeCreated: 创建节点事件
1 | [zk: localhost:2181(CONNECTED) 38] stat /ccomma watch |
NodeDataChanged: 修改节点数据事件
1 | [zk: localhost:2181(CONNECTED) 40] get /ccomma watch |
NodeDeleted: 删除节点事件
1 | [zk: localhost:2181(CONNECTED) 43] delete /ccomma |
NodeChildrenChanged: 子节点变更事件(修改子节点不会触发事件)
创建:
1
2
3
4
5
6
7
8[zk: localhost:2181(CONNECTED) 47] ls /ccomma watch
[]
[zk: localhost:2181(CONNECTED) 48] create /ccomma/abc data
WATCHER::
WatchedEvent state:SyncConnected type:NoteChildrenChanged path:/ccomma
Created /ccomma/abc删除:
1
2
3
4
5
6
7[zk: localhost:2181(CONNECTED) 49] ls /ccomma watch
[abc]
[zk: localhost:2181(CONNECTED) 48] delete /ccomma/abc
WATCHER::
WatchedEvent state:SyncConnected type:NoteChildrenChanged path:/ccomma
4. watcher 原理框架
过程:
- zk 客户端向 zk 服务器注册 watcher 的同时,会将 watcher 对象存储在客户端的 watchManager。
- zk 服务器触发 watcher 事件后,会向客户端发送通知,客户端线程从 watchManager 中回调 watcher 执行相应的功能。
watchManager:
Zk 服务器端 watcher 的管理者。负责 watcher 事件的触发。
从两个维度维护 watcher
- watchTable:从数据节点的粒度来维护
- watch2Paths:从 watcher 的粒度来维护
1
2
3
4
5
6
7
8
9class WatchManager {
private final Map<String, Set<Watcher>> watchTable = new HashMap<String, Set<Watcher>>();
private final Map<Watcher, Set<String>> watch2Paths = new HashMap<Watcher, Set<String>>();
Set<Watcher> triggerWatch(String path, EventType type) {
return triggerWatch(path, type, null);
}
}