zookeeper的watch监听机制,用于监听节点数据变化。当watch监听的数据发生变化时,通知该watch的client,即watcher。
那么既然有watch监听数据变化事件,就有对应的事件类型和状态类型。
zk连接状态类型:
- KeeperState.Disconnected:客户端连接断开
- KeeperState.SyncConnected:客户端和服务器的某一个节点建立连接,并完成一次version、zxid的同步。
- KeeperState.AuthFailed:客户端进行连接认证失败
- KeeperState.Expired:连接过期。客户端和服务器在ticktime的时间周期内,是要发送心跳通知的,该时间内若没有检测到心跳,则认为连接过期。
znode节点事件类型:
- EventType.NodeCreated:节点被创建
- EventType.NodeDataChanged:节点数据被修改
- EventType.NodeChildredChanged:节点的直接子节点被创建、被删除、子节点数据发生变更
- EventType.NodeDeleted:节点被删除
- EventType.None:当zookeeper客户端的连接状态发生变更时,即KeeperState.Expired、KeeperState.Disconnected、KeeperState.SyncConnected、KeeperState.AuthFailed状态切换时,描述的事件类型为EventType.None
zk连接状态与znode节点事件对应关系:
zookeeeper实现watch监听:
实现Watcher接口,重写process方法:
class ZookeeperClient implements Watcher{
private static final String host = "192.168.5.180:2181,192.168.5.182:2181,192.168.5.183:2181";
private static CountDownLatch countDownLatch = new CountDownLatch(1);
public static void main(String[] args) throws IOException {
ZooKeeper zooKeeper = new ZooKeeper(host, 3000,new ZookeeperClient());
try {
countDownLatch.await();
zooKeeper.exists("/test1", true); // true 表示开启监听,false关闭监听
zooKeeper.create("/test1", "123".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void process(WatchedEvent event) {
countDownLatch.countDown();
System.out.println(event.getType());
}
}
输出结果:
Zookeeper中所有读操作(getData(),getChildren(),exists())都可以设置Watch选项。Watch事件具有one-time trigger(一次性触发)的特性,如果Watch监视的Znode有变化,那么就会通知设置该Watch的客户端。
watch机制特性:
-
一次性触发器:客户端在Znode设置了Watch时,如果Znode内容发生改变,那么客户端就会获得Watch事件,而Watch事件一旦被触发,Znode设置的Watch事件就被取消,需要重新添加Watch事件。
-
发送至客户端:Watch事件是异步发送到Client。Zookeeper可以保证客户端发送过去的更新顺序是有序的。
-
设置watch的数据内容:Znode改变有很多种方式,例如:节点创建,节点删除,节点改变,子节点改变等等。Zookeeper维护了两个Watch列表,一个节点数据Watch列表,另一个是子节点Watch列表。getData()和exists()设置数据Watch,getChildren()设置子节点Watch。所以watch可以设置监听当前节点或子节点。
Zookeeper Watcher的运行机制
- Watch是轻量级的,其实就是本地JVM的Callback,服务器端只是存了是否有设置了Watcher的布尔类型。(源码见:org.apache.zookeeper.server.FinalRequestProcessor;参考文章:https://blog.csdn.net/artaganan8/article/details/92771483)
- 在服务端,在FinalRequestProcessor处理对应的Znode操作时,会根据客户端传递的watcher变量,添加到对应的ZKDatabase(org.apache.zookeeper.server.ZKDatabase)中进行持久化存储,同时将自己NIOServerCnxn做为一个Watcher callback,监听服务端事件变化
- Leader通过投票通过了某次Znode变化的请求后,然后通知对应的Follower,Follower根据自己内存中的zkDataBase信息,发送notification信息给zookeeper客户端。
- Zookeeper客户端接收到notification信息后,找到对应变化path的watcher列表,挨个进行触发回调。