Detailed explanation of ZooKeeper watchpoints

It is common for an application to need to know the state of a ZooKeeper node, such as in master-slave mode slave nodes need to know if the master node has crashed.

Rotational training is inefficient, especially when the expected frequency of change is low.

ZooKeeper provides a watch, an important mechanism for dealing with node changes. The client registers a notification request for the specified znode node and receives a single notification when the node state changes.

single notification

A watchpoint is a one-time trigger. An application registers a watchpoint with a node and sends a notification to the application when the node triggers an event for the first time.

Watchpoints are associated with a session, and when a client disconnects from one ZooKeeper server, it connects to another server in the ensemble and sends an untriggered watchlist to the server. If the monitored node has changed, a notification will be sent to the client, otherwise the watchpoint will be registered on the new server.

A single-triggered notification can miss events, such as events that occur in the time between receiving the notification and registering a new watchpoint. Loss events are usually not impactful though, and node changes can be caught by reading the node state when registering a new watchpoint.

Set up watchpoints

Watchpoints can be set for all reads in ZooKeeper, including getData, getChildren, and exists.

To use watchpoints, you need to implement the Watcher interface and override the void process(WatchedEvent event) method. The WatchedEvent contains ZooKeeper's session state (KeeperState) and event type (EventType).

Event types include NodeCreated, NodeDeleted, NodeDataChanged, NodeChildrenChanged, and None. The first 3 types refer to a single znode node, the fourth, NodeChildrenChanged, refers to the children of the monitored node. None indicates a ZooKeeper session state change.

event type Set watch point mode
NodeCreated Set a watchpoint via the exists call
NodeDeleted Set watchpoints via exists or getData calls
NodeDataChanged Set watchpoints via exists or getData calls
NodeChildrenChanged Set watchpoint via getChildren call

Atomic manipulation

ZooKeeper added the feature of atomic operations in version 3.4.0. Multiple ZooKeeper operations can be performed atomically through multiop, and these operations either all succeed or all fail.

When using multiop, first create an Op object containing ZooKeeper operations, and then put multiple Op objects into an Iterable type object for the client to call, such as:

Op deleteZnode(String path) {
    return Op.delete(path, -1);
}

Op createZnode(String path, String data) {
    return Op.create(path, data.getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
}

List<OpResult> results = zk.multi(Arrays.asList(deleteZnode("/a"), createZnode("b", "data")));

The multi method also has an asynchronous version. The definitions of the synchronous and asynchronous methods are as follows:

public List<OpResult> multi(Iterable<Op> ops) throw InterruptedException,KeeperException;
public void multi(Iterable<Op> ops, MultiCallback callback, Object context);

Transaction encapsulates the multi method and provides a simpler way of calling. You can add operations and submit transactions by creating a Transaction object.

List<OpResult> results = zk.transaction().delete("/a", -1).create("/b", "data".getBytes()
        , ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT).commit();

Another function provided by multi is to check the version number of the znode. If the input znode node does not match the version number, the call to multi will fail.

public static Op check(String path, int version);

remove hidden channels

The state of ZooKeeper will be replicated among all servers, and the servers will agree on the order of state changes and update the state in the same order. But in fact, the server seldom performs update operations at the same time, and if the communication is performed through a hidden channel, the state may be inconsistent.

For example, Client-1 connects to Server-1, Client-2 connects to Server-2, and the data in the /z node changes from a to b.

Server-1 will send a notification to Client-1 to update the status. Client-1 will send a message of /z node change to Client-2 after receiving the notification. Client-2 will then operate through Server-2. Without updating the state of the /z node, stale data is read.

Client-1 sends a message to Clinet-2, which is a hidden channel, which will lead to errors. The correct way is that Client-2 only receives messages through the ZooKeeper server, eliminating the hidden channel.

Avoid setting too many watchpoints on the same node

When a node changes, it will send a message to the client that sets the monitoring point. If too many monitoring points are set for the same node, there will be a peak of sending messages when the node state changes, which may affect performance.

If conditions permit, it is best to set a small number of monitoring points on the node, ideally only one.

For example, multiple clients are competing to acquire a lock: one client can acquire a lock by creating a temporary node, and other clients can set monitoring points on this node; it can also be changed to allow the client to create an ordered temporary node, and the client with the smallest serial number To acquire the lock, other clients only set monitoring points compared to the nodes whose serial numbers are 1 smaller than their own.

A watchpoint will occupy about 300 bytes of memory on the server side, and you need to pay attention to the number of watchpoints during development.

original address

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325388254&siteId=291194637
Recommended