开始
curator 是Zookeeper的客户端框架。curator在zookeeper原生API的基础上进行了封装,提供了注册,watch,以及recipe,分布式锁,Master选举等等。他帮助我们屏蔽了zookeeper复杂的原生api。
本文将介绍是如何基于curator的cache来实现对Zookeeper节点的watch。
Zookeeper的watch
Zookeeper通常以远程服务的方式被调用。每次访问znode时候,客户端需要额外获取节点中的内容,这种代价是非常大的。因为这样会导致更高的延迟,而且Zookeeper需要更多的操作。
为了解决这个问题,Zookeeper采用了Watcher机制实现数据的发布/订阅功能。该机制在被订阅对象发生变化时会异步通知客户端,因此客户端不必在Watcher注册后轮询阻塞,从而减轻了客户端压力。
wacth在Zookeeper原生中是一个单次触发的操作,即一个wacth触发一个通知。为了接受多个通知的话,客户端必须在每次通知后设置一个新的watch。如下图所示
通知watch 的重要保障是。对同一个znode节点的操作,先向客户端传送通知,然后再对该节点进行变更。
在了解了zookeeper中的watch后,我们来看看curator包是如何实现watch的。
curator 使用cache来实现watch
curator的cache是一种缓存机制,借助cache,curator实现了watch。cache在客户端缓存了znode的各种状态,当感知到zk集群的znode状态变化,会触发event事件,注册的监听器会处理这些事件。
curator有3种watch
NodeCache
NodeCache是用来监听节点的数据变化的,当监听的节点的数据发生变化的时候就会回调对应的函数。
public class ZkCacheListener implements NodeCacheListener{
public void nodeChanged thorw Exception{
}
}
public class Listener {
private final NodeCache nodeCache = new NodeCache(client, parentPath, false);
//省略start
public void addDataListener(){
nodeCache..getListenable().addListener(new ZkCacheListener());
}
}
NodeCache 能够监听自身节点的变化,不能监听子节点的变化
PathChildrenCache
(1)只能监听子节点,监听不到当前节点
(2)不能递归监听,子节点下的子节点不能递归监控
public class ZkCacheListener implements PathChildrenCacheListener{
public void childEvent(CuratorFramework client, PathChildrenCacheEvent e) thorw Exception{
// event 主要有两个参数
// Type :CHILD_ADDED,CHILD_UPDATED,CHILD_REMOVED 表示event事件的类型,增加删除更新
// ChildData: 子节点中的数据
}
}
TreeCache
TreeCache观察的是当前ZNode节点的所有数据。而TreeCache节点树缓存是PathChildrenCache的增强,不光能监听子节点,也能监听节点自身。
public class ZkCacheListener implements TreeCacheListener{
public void childEvent(CuratorFramework client, TreeCacheEvent event){
// event也含有Type字段
// Type :NODE_ADDED,NODE_UPDATED,NODE_REMOVED
}
}
cache解决了什么?
在一开始我们说到zookeeper 原生的watch是一个单次的操作,一个wacth触发一个通知。也就是说,watch是一次性的,如果要反复使用,就要反复的注册。这在开发当中十分的头疼,而Curator的cache帮我们解决了这个问题。
Cache对ZooKeeper事件监听进行了封装,能够自动处理反复注册监听。