在实际中我们客户端希望能够时时感知到数据的变化,这时候ZK的watch机制就起了很重要的作用。

 

一、ZooKeeper 的watch机制

         ZooKeeper支持 Watch,客户端可以在znode上设置 Watch。

         znode更改时,将触发并删除监视。触发监视后,客户端会收到一个数据包,说明znode已更改。

3.6.0中的新增功能:

         客户端还可以在znode上设置永久性的递归监视,这些监视在触发时不会删除,并且会以递归方式触发注册znode以及所有子znode的更改。

支持 Watch的 客户端命令:

  • stat path [watch]
  • ls path [watch]
  • ls2 path [watch]
  • get path [watch]

新版本的方式:

  • stat -w path
  • ls -w path
  • ls2 -w path
  • get -w path

 

 

二、ZooKeeper 的watch栗子

         使用命令get -w <path>进行监听:

         如果使用get /test/test1  watch,也能够监听,但是会有一个警告:

         此时使用另外一个客户端去更改 /test/test1 节点的数据,我们就可以看到原来的客户端自动收到了一个WATCHER 通知。

         如果我们在进行set操作,并没有再次受到通知,这个就是ZK的一个监听机制决定的:znode更改时,将触发并删除监视,也就是说只能监听一次。

         如果我们监听的是节点/test,但是我们修改的是/test/test1的节点的话,这个是监听不到的。

         在3.6.x版本中支持:在znode上设置永久性的递归监视,这些监视在触发时不会删除,并且会以递归方式触发注册znode以及所有子znode的更改。那么这个怎么呢?

         先看下我们当前的ZK版本是否满足3.6.x:

 

         满足的情况下,那么要怎么操作呐?使用help看下说明:

 

         使用方式:addWatch [-m mode] path

         可选模式是[PERSISTENT,PERSISTENT_RECURSIVE]之一-默认为PERSISTENT_RECURSIVE。

         PERSISTENT:只有当前监听的节点有变化了,才能收到通知,会持续的收到每次的通知。

         PERSISTENT_RECURSIVE:当前节点和子节点有变化了,就会收到通知,会持续的收到每次的通知。

 

三、watch监听的事件类型和状态类型

事件类型:(znode节点相关的):

EventType.NodeCreated

EventType.NodeDataChanged

EventType.NodeChildrenChanged

EventType.NodeDeleted

 

状态类型:(是跟客户端实例相关的):

KeeperState.Disconnected

KeeperState.SyncConnected

KeeperState.AuthFailed

KeeperState.Expired

 

四、watch特性

         wather的特性:一次性客户端串行执行轻量

一次性(3.6.x支持永久递归监视):对于ZK的watcher,你只需要记住一点:zookeeper有watch事件,是一次性触发的,当watch监视的数据发生变化时,通知设置了该watch的client,即watcher,由于zookeeper的监控都是一次性的,所以每次都必须监控。

         客户端串行执行:客户端watcher回调的过程是一个串行同步的过程,这为我们保证了顺序,同时需要开发人员注意一点,千万不用因为一个watcher的处理逻辑影响了整个客户端的watcher回调。

         轻量:WatcherEvent是ZooKeeper整个Watcher通知机制的最小通知单元。整个单元结构只包含三部分:通知状态,事件类型和节点路径。也就是说Watcher通知非常的简单,只会告诉客户端发生了事件而不会告知其具体内容,需要客户自己去进行获取,而不会直接提供具体的数据内容。

 

 

 

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐