Is there a way to add watcher queue in zookeeper?

2020-07-09 02:46发布

问题:

I am using node-zookeeper-client for java script as a zookeeper client.

I have something like this:

const setWatch = (path, functionToExecuteOnTrigger) => {
  client.getData(path, (event) => {
      // watcher set here
      functionToExecuteOnTrigger(event);
  }, null)
  // null because we are only setting watch here and do not need data
}

This function will set a watch at a path in the zookeeper. Once a watch is triggered, the watcher callback will be called and an appropriate function to be called on the watch is called.

for watches set like this:

setWatch('/data1', function1);
setWatch('/data2', function2);

so function1 is executed for watch triggered in data1 node and function2 executed for watch triggered in data2 node

Now if I have to continuously keep watch at the nodes so that each time something is changed, I would have to re-register the watches immediately after they are triggered:

const setWatch = (path, functionToExecuteOnTrigger) => {
  client.getData(path, (event) => {
      // watcher set here
      // immediately set another watch for the same function
      setWatch(path, functionToExecuteOnTrigger);
      functionToExecuteOnTrigger(event);
  }, null)
  // null because we are only setting watch here and do not need data
}

Now the things I know about zookeeper watches are:

  • There are 3 types of watches; data, children and exist
  • Watchers are one time trigger, i.e. once they are triggered, one has to re-register them to obtain further triggers.

Because of the 2nd point mentioned above, there is a chance of missing changes that occur between the period of watch triggered and re-registering the watch. As mentioned in the official documentation of zookeeper.

So I was wondering if there is a way in which we could actually set multiple watches for the same node (in a queue sort of way) and for each time a watch is triggered, only a single trigger callback is called. Something like this:

setWatch(node, functionToTrigger, noOfWatchesInQueue)

So we will be setting multiple watch for the same node and for a trigger, only one of those set watches are triggered. Hence, if I set 3 watches in queue for the same node i.e

for trigger 1, watch1 is activated
for trigger 2, watch 2 and so on...

That way no event is missed during the time taken to re-register the watch.

Is there a way to obtain this ?? I do not know if this is already been done somewhere, any kind of research material or implementations regarding the issue would be helpful as well.

回答1:

There's no way in Zookeeper to set multiple watches on the same node with a single operation. This is by design.

As you mentioned, (and according to the documentation) you can only set a single watch when you read the value of a node. This way you will always have a the most up-to-date value of a node and notified when it changes. This is what ZK offers, not more.

Zookeeper watches aren't event queues and it's not guaranteed that you'll receive every single event.

I think it'd be better to describe your use case and try to get an answer for what would be the best tool to accomplish it, because ZK might not be suitable.



回答2:

I think you should always do following:

  1. set watch for znode

  2. retrieve actual value of znode

In this way, you will always know the latest version of znode, and will be notified on future change. Notice also that each znode has version numbers - you can check easily whether it has changed.