有条件的更新和监视-watch
ZooKeeper支持watch的概念。客户端可以在znode上设置watch。znode更改时,将触发并删除监视。
触发监视后,客户端会收到一个数据包,说明znode已更改。如果客户端与ZooKeeper服务器之一之间的连接断开,则客户端将收到本地通知。
zookeeper提供了一种监控数据节点变动的机制。
一般我们监控一个东西,一般有2种方式:
1、几秒一轮询,这样间隔询问一下,但会有时效性。
2、事件监听,当数据发生变动时,会产生事件,我们一般可以事先给予回调处理,等事件触发时可以实时的执行我们的回调处理。
Zookeeper中所有读操作(getData(),getChildren(),exists())都可以设置Watch。
关于watch,我们更多的还是使用API进行实践,才能体会。
API
1、建立1个maven项目。
2、导入pom依赖。
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.6</version>
</dependency>
3、开始编写代码
首先需要建立连接:
//建立zookeeper连接
ZooKeeper zooKeeper = new ZooKeeper("192.168.221.66:2181,192.168.221.68:2181,192.168.221.70:2181,192.168.221.72:2181",
3000, //session有效期,创建的临时节点会在该客户端失去连接的这个期限后,进行删除
//会话级别的监听,用于监听session级别的事件
watchedEvent -> {
System.out.println("sessionEvent:"+watchedEvent);
Watcher.Event.EventType type = watchedEvent.getType();
switch (watchedEvent.getState()) {
case Unknown:
break;
case Disconnected:
System.out.println("Disconnected");
break;
case NoSyncConnected:
break;
case SyncConnected:
System.out.println("SyncConnected");
countDownLatch.countDown();
break;
case AuthFailed:
break;
case ConnectedReadOnly:
break;
case SaslAuthenticated:
break;
case Expired:
break;
}
});
各种读操作都可以使用watch,这里以获取数据为例:
Stat stat = new Stat();
//绑定watch后,之后该节点的改变都将会被监听,并且进入该回调处理。
//此watch用于监听节点路径级别的
zooKeeper.getData("/xxoo", new Watcher() {
@Override
public void process(WatchedEvent watchedEvent) {
switch (type) {
case None:
break;
case NodeCreated:
System.out.println("path-event: node-create");
break;
case NodeDeleted:
break;
case NodeDataChanged:
System.out.println("path-event: NodeDataChanged,path:" + watchedEvent.getPath());
try {
//watch只会触发一次,因此可以使用这种方式进行重复绑定
zooKeeper.getData(watchedEvent.getPath(), this,stat);
} catch (KeeperException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
break;
case NodeChildrenChanged:
break;
}
}
},stat);
接下来演示一下创建节点:
String s = zooKeeper.create("/zk_test/xxoo", "he".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
更新节点:
Stat stat2 = zooKeeper.setData("/xxoo", "hello".getBytes(), stat.getVersion());
当然,zookeeper的API对于这些操作提供了同步和异步两个版本,上述的都是基于同步的,下面来演示一个异步的:
以更新节点为例
zooKeeper.setData("/xxoo", "hello2".getBytes(),stat.getVersion(), new AsyncCallback.StatCallback() {
@Override
public void processResult(int rc, String path, Object ctx, Stat stat1) {
System.out.println(ctx);
System.out.println("set:" + s);
}
},"CTX");