Zookeeper 从入门到入土③:Watcher

概述: 为一个节点注册监听器,在节点状态发生改变时,会给客户端发送消息。

1. 特性

  • 一次性: watcher 触发后立即销毁。
  • 轻量级: watch 是轻量级的,其实就是本地 JVM 的 Callback,服务器端只是存了是否有设置了 watcher 的布尔类型
  • 可见性: Watch 被触发的同时再次读取数据,客户端会得到 Watch 消息再看到更新后的数据。
  • 可能会丢失: 对于一个未创建的 znode 的 exist watch,如果在客户端断开连接期间被创建了,并且随后在客户端连接上之前又删除了,这种情况下,这个 Watch 事件可能会被丢失。

2. 设置 watcher

只有 stat、get、ls 才能设置 watcher

3. 事件类型

NodeCreated: 创建节点事件

1
2
3
4
5
6
7
8
[zk: localhost:2181(CONNECTED) 38] stat /ccomma watch
Note does not exist: /ccomma
[zk: localhost:2181(CONNECTED) 39] create /ccomma data

WATCHER::

WatchedEvent state:SyncConnected type:NoteCreated path:/ccomma
Created /ccomma

NodeDataChanged: 修改节点数据事件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
[zk: localhost:2181(CONNECTED) 40] get /ccomma watch
data
cZxid = 0x15
ctime = Mon May 27 16:09:24 CST 2019
mZxid = 0x15
mtime = Mon May 27 16:09:24 CST 2019
pZxid = 0x15
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 4
numChildren = 0
[zk: localhost:2181(CONNECTED) 41] set /ccomma 123

WATCHER::

WatchedEvent state:SyncConnected type:NoteDataChanged path:/ccomma
cZxid = 0x15
ctime = Mon May 27 16:09:24 CST 2019
mZxid = 0x16
mtime = Mon May 27 16:17:17 CST 2019
pZxid = 0x15
cversion = 0
dataVersion = 1
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 3
numChildren = 0

NodeDeleted: 删除节点事件

1
2
3
4
5
[zk: localhost:2181(CONNECTED) 43] delete /ccomma

WATCHER::

WatchedEvent state:SyncConnected type:NoteDeleted path:/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
    9
    class 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);
    }
    }