watch是什么
watch
是zookeeper
的核心功能,client
可以监控zookeeper
中node
的状态变化以及node
子节点的状态变化,一旦这些状态状态发生了改变,zookeeper
就会通知这个node
上的client
,这样client就能做相应的业务逻辑了.
依据ZooKeeper Watches.我们可以知道zooKeeper
中的所有读操作,也就是getData()
、getChildren()
和exists()
都可以设置一个watch
,以下是zooKeeper
对watch
的定义:watch
事件是一次性触发器,当监控的node
数据发生变化时发生,事件发送给设置watch的客户端.
watch的三个要点
在这个watch
的定义中有三个要点需要考虑:
一次性: 当
node
的数据发生变化时,就是产生了一个事件,watch
是一次性的,在被事件触发后这个watch
就会失效.例如,如果client
执行getData("/znode1",true)
,然后/znode1
的数据被更改或删除,client
将获得/znode1
的watch
事件。如果/znode1
再次更改,则不会发送任何watch
事件,除非客户端再次读取并设置了一个新的watch
- 这是一个很重要的知识点,就是一个
watch
会被反复的一类事件反复的触发么? 答案是不能,触发一次后watch
就失效了,你需要再次设置watch来重新监听事件
- 这是一个很重要的知识点,就是一个
- 有序性: 发生到client的watch事件和更新node数据的操作是有先后顺序的,也就是先进行了node数据更新,node数据更新成功后才会产生watch事件.client才能接到通知.可能有人认为zookeeper只要接到node数据更新操作就会产生watch事件,这个假设是错的,zookeeper做到分布式一致性其实是有严格的有序性的.watch事件是被异步发送到client的,同时对于同一个watch事件如果有多个client监听的话,由于网络延迟这些client可能会在事件的接受时间上有细微的偏差,不同客户端看到的所有操作依然有一致的顺序
- watch事件是有类型的: node数据的改变可以分为2个了类型,一个是node的数据被改变,例外一个是node的子节点被改变. zookeeper因此维护了2种watch事件列表:getData()和exists()可以设置数据改变相关的watch,getChildren()可以设置node子节点相关的watch.我们在设置watch的时候需要按照上面的类型进行选择.
zookeeper对watch的保障
zookeeper维护了如下的保证
- 有序性: watch是根据其他事件、其他watch和异步响应来排序的。ZooKeeper客户端库确保所有的事情都被有序地调度。
- 事件产生在事件发送前: 一个事件必须在数据操作成功后产生,然后才会发给watch. 事件的产生和事件的发送不是并行的,必须是先后关系
- 事件的有序性: zookeeper会有多个watch,这些watch事件的产生的顺序是和数据操作的顺序一致的
使用watch要注意如下的问题
使用watch要注意下面几点:
- watch是一次性的,当watch被触发然后发送给client后,后面同类的事件是不会再次发送到client了,你要持续的监听只能重新添加watch
- 因为标准的手表是一次性触发器,并且在获取事件和发送一个新的请求来获取手表之间有延迟,你不能可靠地看到发生在ZooKeeper节点上的每一个变化。准备好处理znode在获取事件和再次设置手表之间多次更改的情况。(你可能并不在乎,但至少意识到这种情况可能会发生。)
- A watch object, or function/context pair, will only be triggered once for a given notification. For example, if the same watch object is registered for an exists and a getData call for the same file and that file is then deleted, the watch object would only be invoked once with the deletion notification for the file.
- When you disconnect from a server (for example, when the server fails), you will not get any watches until the connection is reestablished. For this reason session events are sent to all outstanding watch handlers. Use session events to go into a safe mode: you will not be receiving events while disconnected, so your process should act conservatively in that mode.
watch注册与处触发
如图下图所示:
- exists操作上的watch,在被监视的Znode创建、删除或数据更新时被触发。
- getData操作上的watch,在被监视的Znode删除或数据更新时被触发。在被创建时不能被触发,因为只有Znode一定存在,getData操作才会成功。
- getChildren操作上的watch,在被监视的Znode的子节点创建或删除,或是这个Znode自身被删除时被触发。可以通过查看watch事件类型来区分是Znode,还是他的子节点被删除:NodeDelete表示Znode被删除,NodeDeletedChanged表示子节点被删除。
Watch由客户端所连接的ZooKeeper服务器在本地维护,因此watch可以非常容易地设置、管理和分派。当客户端连接到一个新的服务器时,任何的会话事件都将可能触发watch。另外,当从服务器断开连接的时候,watch将不会被接收。但是,当一个客户端重新建立连接的时候,任何先前注册过的watch都会被重新注册。
代码演示
设置当前节点的的watch
[zk: localhost:2181(CONNECTED) 22] create /w1 thinktik
Created /w1
# 设置对当前节点的监控
[zk: localhost:2181(CONNECTED) 23] get -w /w1
thinktik
# 当前节点变更后会有通知
[zk: localhost:2181(CONNECTED) 24] set /w1 think
WATCHER::
WatchedEvent state:SyncConnected type:NodeDataChanged path:/w1
设置对子节点的监控
# 监控当前节点的子节点相关的监控
[zk: localhost:2181(CONNECTED) 25] ls -w -R /w1
/w1
# 子节点发送变化时会有通知
[zk: localhost:2181(CONNECTED) 26] create /w1/sw1
WATCHER::
WatchedEvent state:SyncConnected type:NodeChildrenChanged path:/w1
Created /w1/sw1
本文原创链接: zookeeper watch
参考:
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。