Typical application scenarios of ZooKeeper

"Principle and Practice of Distributed Consistency from Paxos to Zookeeper" Reading Notes

This article: Summarize the brain map Address: Brain map

foreword

All typical application scenarios take advantage of the following features of ZK:

  1. Strong consistency: In the case of high concurrency, it can ensure that the creation of nodes must be globally unique.
  2. Watcher mechanism and asynchronous notification: You can add monitoring to the specified node, and when the node changes, you will receive a notification from ZK.

Data publish and subscribe (configuration center)

A common application is the configuration center, where the publisher publishes data to one or more nodes of ZooKeeper for subscribers to subscribe to data, thereby achieving the purpose of dynamically obtaining data, realizing centralized management of configuration information and dynamic updating of data.

There are generally two design patterns for a publish-subscribe system: Push and Pull. In the push mode, the server actively sends data updates to all subscribed clients; while in the pull mode, the client actively initiates a request to obtain the latest data. Usually, the client uses the method of polling and pulling regularly.

ZooKeeper uses a combination of push and pull: the client registers the node that it needs to pay attention to with the server. Once the data of the node is changed, the server will send a Watcher event notification to the corresponding client, and the client receives this After the message is notified, it is necessary to actively go to the server to obtain the latest data.

Usually, the data placed on the configuration center has the following characteristics:

  1. The amount of data is usually small.
  2. The data content changes dynamically at runtime.
  3. All machines in the cluster share the same configuration.

naming service

It refers to the address of the resource or service obtained by the specified name, and the information of the provider. Using Zookeeper, it is easy to create a global path, and this path can be used as a name, which can point to the cluster in the cluster, the address of the service provided, the remote object, etc. Simply put, using Zookeeper as a naming service is to use the path as the name, and the data on the path is the entity that its name points to.

The open source distributed service framework Dubbo of Alibaba Group uses ZooKeeper as its naming service to maintain a global list of service addresses. In the Dubbo implementation:

When the service provider starts, it /dubbo/${serviceName}/providerswrites its own URL address to the specified node directory on ZK, and this operation completes the service release.

When the service consumer starts, it subscribes /dubbo/{serviceName}/providersto the provider URL address in the /dubbo/{serviceName} /consumersdirectory, and writes its own URL address to the directory.

Note that all addresses registered with ZK are ephemeral nodes, which ensures that service providers and consumers can automatically sense resource changes. In addition, Dubbo also provides monitoring for service granularity by subscribing /dubbo/{serviceName}to the information of all providers and consumers in the directory.

Distributed coordination/notification

  1. Distributed timing tasks:
  • Fair way: Create temporary non-sequential nodes in the specified directory at the same time, and successfully created nodes are eligible to execute tasks
  • Unfair method: Create temporary sequential nodes in the specified directory at the same time, and the node with the smallest node order gets the execution permission.
  1. Heartbeat detection:
    Based on the temporary node feature of ZooKeeper, different machines can create temporary child nodes under a specified node of ZooKeeper, and different machines can judge whether the corresponding client machine is alive according to this temporary node. In this way, the detection system and the detected system do not need to be directly associated, but are associated through a node on ZooKeeper, which greatly reduces system coupling.

  2. HA: Same heartbeat detection.

Distributed lock

The use of ZK to build distributed locks takes advantage of ZK's ability to ensure the uniqueness of child node creation in the case of high concurrency.

unfair exclusive lock

In a specific directory, create a temporary child node. If the creation is successful, it means that the lock is obtained. If the creation fails, return the lock failure directly or monitor the specified node, and then wait for the successfully locked node to release the lock before trying to acquire the lock by itself.

fair exclusive lock

Create a permanent node with the name of the lock key, and then all nodes competing for the lock create a temporary ordered node under the permanent node, and the node with the smallest sequence number acquires the lock. The node with a non-minimum sequence number monitors the previous node , not all nodes. After receiving the notification, it verifies whether it is the node with the lowest sequence number. If it is, it means that it has acquired the lock, otherwise it listens to the previous node again.

Shared lock (S lock)

All nodes that try to lock create a temporary sequence node in the specified directory. /shared_lock/[hostname]-请求类型-序号A temporary sequence node in the form of, for example /shared_lock/192.168.0.1-R-00000001, represents a shared lock; /shared_lock/192.168.0.1-W-00000001, represents a write lock.

According to the definition of a shared lock, different transactions can read the same data object at the same time, and the update operation must be performed without any transaction currently reading and writing. Based on this principle, let's see how to determine the distributed read and write order through ZooKeeper nodes:

  1. After the node is created, obtain /shared_lockall the child nodes under the node, and determine the order of its own node number in all the child nodes.
  2. for read requests
  • If there is no child node with a smaller serial number than its own, or all child nodes with a smaller serial number than its own serial number are read requests, then the table name itself has successfully acquired the shared lock and starts to execute the read logic at the same time.
  • If a child node with a smaller serial number than its own has a write request, it needs to enter the wait.
  1. For write requests: If you are not the child node with the smallest sequence number, you need to enter the wait.
  2. After receiving the Watcher notification, repeat step 1.

Master election

Using the strong consistency of ZooKeeper, it can well ensure that the creation of nodes can guarantee global uniqueness in the case of distributed high concurrency, that is, ZooKeeper will ensure that the client cannot repeatedly create an existing data node. When multiple machines compete for the Master role at the same time, everyone creates a temporary node in the specified directory. During this process, only one client can successfully create the node, then the machine where the client is located is called the Master. At the same time, clients that have not been successfully created register a listening event on the node to monitor whether the current Master machine is alive. Once the current Master is found to be down, the remaining clients will re-elect the Master.

Distributed queue

FIFO first in first out queue

The first-out queue with the smallest sequence number:

  1. All nodes in the queue will create ordered nodes in the specified directory.
  2. getChildren()Get all the child nodes under the node by calling the interface, that is, get all the elements in the queue.
  3. Determine the order of your own node number in all child nodes
  4. If you are not the child node with the smallest serial number, you need to enter the wait and register Watcher monitoring with the last node with a smaller serial number than your own.

Barrier: Distributed Barrier

Distributed Barrier stipulates that the elements of a queue must be gathered before they can be arranged uniformly, otherwise they will keep waiting. This often occurs in the application scenarios of large-scale distributed parallel computing: the final combined calculation needs to be performed based on the sub-results of many parallel calculations. The general design ideas are as follows:

  • At the beginning, the /queue_barriernode is an existing default node, and the data content of its node is assigned a number n to represent the Barrier value. For example, n=10 means that only when /queue_barrierthe number of child nodes under the node reaches 10, it will be opened. Barrier.

  • All clients will /queue_barriercreate a temporary node under the node.

  • After the creation is successful, the data content of the node is obtained by calling the getData()interface : 10./queue_barrier
  • Get all the child nodes under the node by calling the getChildren()interface , that is, get all the elements in the queue, and register the Watcher monitoring of the change of the child node list at the same time./queue_barrier
  • Count the number of child nodes.
  • If the number of child nodes is less than 10, it needs to enter the wait.
  • After receiving the Watcher notification, repeat step 2.

Notice

For scenarios involving sequential ordered nodes, sorting waits. You don't need to monitor the parent node or all other sibling nodes, just monitor the first node with a smaller serial number than yourself, which can prevent a large number of useless Watchernotifications from being received.

Guess you like

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