在深⼊讨论监视点之前,我们先了解⼀些术语。我们所说的事件(event)表⽰⼀个znode节点执⾏了更新操作。⽽⼀个监视点(watch)表⽰⼀个与之关联的znode节点和事件类型组成的单次触发器(例如,znode节点的数据被赋值,或znode节点被删除)。当⼀个监视点被⼀个事件触发时,就会产⽣⼀个通知(notification)。通知是注册了监视点的应⽤客户端收到的事件报告的消息。
当应⽤程序注册了⼀个监视点来接收通知,匹配该监视点条件的第⼀个事件会触发监视点的通知,并且最多只触发⼀次。例如,当znode节点/z被删除,客户端需要知道该变化(例如,表⽰备份主节点),客户端在/z节点执⾏exists操作并设置监视点标志位,等待通知,客户端会以回调函数的形式收到通知。
客户端设置的每个监视点与会话关联,如果会话过期,等待中的监视点将会被删除。不过监视点可以跨越不同服务端的连接⽽保持,例如,当⼀个ZooKeeper客户端与⼀个ZooKeeper服务端的连接断开后连接到集合中的另⼀个服务端,客户端会发送未触发的监视点列表,在注册监视点时,服务端将要检查已监视的znode节点在之前注册监视点之后是否已经变化,如果znode节点已经发⽣变化,⼀个监视点的事件就会被发送给客户端,否则在新的服务端上注册监视点。
单次触发是否会丢失事件
答案是肯定的。⼀个应⽤在接收到通知后,注册另⼀个监视点时,可能会丢失事件,不过,这个问题需要再深⼊讨论。丢失事件通常并不是问题,因为任何在接收通知与注册新监视点之间的变化情况,均可以通过读取ZooKeeper的状态信息来获得。
假设⼀个从节点接收到⼀个新任务分配给它的通知。为了接收新任务,从节点读取任务列表,如果在通知接收后,又给这个从节点分配了更多的任务,在通过getChildren调⽤获取任务列表时会返回所有的任务。同时调⽤getChildren时也可以设置新的监视点,从⽽保证从节点不会丢失任务。
实际上,将多个事件分摊到⼀个通知上具有积极的作⽤,⽐如,应⽤进⾏⾼频率的更新操作时,这种通知机制⽐每个事件都发送通知更加轻量化。举个例⼦,如果每个通知平均捕获两个事件,我们为每个事件只产⽣了0.5个通知,⽽不是每个事件1个通知。
我们的交流基地,“JAVA互联网技术交流:789650498”欢迎小伙伴们一起来交流: