zookeeper - watcher(9)

watcher的特征

    zookeeper的一大特点之一就是watch机制,所有基于zookeeper的消息通知机制基本上都是建议在watcher机制之上的,比如业界比较有名的由360公司开源的Qconf的底层就是基于这个实现的,本章其实就是想将zookeeper的watcher的数据存储、watcher的添加、watcher的触发整个过程讲解清楚,方便大家有个清晰的认识。

watch特性


watcher的存储

watcher的存储

说明:

     watcher主要分为dataWatches和childWatches,其中dataWatches是保存节点层面的watcher对象的,childWatches是保存子节点层面的watcher对象的。核心的点在于WatchManager数据结构。


watcher的保存结构

说明:

    WatchManager内部主要维持了watchTable(path->watcher)以及watch2Paths(watcher->path)两个映射关系,其实这也就是代表了一个path有多个watcher,或一个watcher同时watch了多个path的场景。

    整个watcher的添加过程其实同时需要修改watchTable和watch2Paths两个map对象,具体的修改操作可以参考上面的代码贴图。


watcher的添加

    zookeeper的watcher的添加一般通过三个途径,分别是通过existsgetDatagetChildren三种方式添加,其中exists用于判断节点是否存在,getData获取节点数据,getChildren获取子节点。其实从这个地方我们可以看出来其实watcher的添加其实是附加动作,基本上都是在主动作的同时添加一下watcher。

    从下面的API我们其实就看出来了,对应上面提到的3个动作提供3个接口用于添加watcher动作。

watcher的添加方式

exists添加watcher

exists的watcher

说明:

    直观的感受就是我们在执行exists的api的时候,我们最终通过statNode的接口保存了watcher,注意这里保存在dataWatches当中


getData添加watcher

getData的watcher

说明:

    直观的感受就是我们再执行getData的时候,我们最终通过addWatch的接口保存了watcher,注意这里保存在dataWatches当中


getChildren添加watcher

getChildren的watcher

说明:

    直观的感受就是我们再执行getData的时候,我们最终通过addWatch的接口保存了watcher,注意这里的保存在childWatches当中


watcher添加过程

数据流入口

说明:

    其实数据是在FinalRequestProcessor当中进行写入的,根据OpCode执行的写入操作,所以基本上我认为通过这个图基本上能够了解到watcher写入的入口了。


watcher的触发

watcher触发后动作

说明:

    从这里我们可以看出来并且印证一个观点,那就是watcher是一次性触发的,原因就在于每次我们triggerWatch的时候我们都会把watcher从watchTable当中移除,根据具体触发的path路径找到对应的watcher,然后移除watcher并触发watcher的后续动作。注意这里触发了watcher。


触发watcher的动作

说明:

    从这里我们可以看出来,触发watcher的几个动作主要包括创建节点(createNode)、删除节点(deleteNode)、数据变更(setData)。



同时触发dataWatches和childWatches

说明:

    从上图可以看出来我们在创建节点的时候会同时判断是否触发dataWatches和childWatches,这也就解释了childWatches是如何被触发的。

你可能感兴趣的:(zookeeper - watcher(9))