In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-01-30 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/01 Report--
This article Xiaobian for you to introduce in detail the "ZooKeeper three distributed lock implementation and complete operation of the code", the content is detailed, the steps are clear, the details are handled properly, I hope that this "ZooKeeper three distributed lock implementation and complete operation of the code" article can help you solve your doubts, following the editor's ideas slowly in-depth, together to learn new knowledge.
Version 1.0
First of all, let's introduce a simple idea of zookeeper to implement distributed locks:
Use a temporary node in the zookeeper to represent the lock, such as creating a temporary child node / exlusive_lock/lock under / exlusive_lock.
All clients scrambled to create this node, but only one client successfully created it.
Successful creation means that the lock was acquired successfully, and this client executes the business logic.
Failed to create a client, listen for / exlusive_lock changes
When the client that acquires the lock completes the execution, delete / exlusive_lock/lock, indicating that the lock is released
After the lock is released, other clients listening for / exlusive_lock changes are notified and scramble again to create temporary child nodes / exlusive_lock/lock. This is equivalent to going back to step 2.
Our program follows the above logic until the lock is preempted and the business logic is executed.
The above is a relatively simple way to implement distributed locks. Can cope with general usage scenarios, but there are two problems:
1. The acquisition order of the lock is not consistent with the original client contention order, which is not a fair lock. Each lock acquisition is the client that grabs the lock first.
2. Herding effect, all clients that do not grab the lock will listen for / exlusive_lock changes. When there are many concurrent clients, all clients will be notified to scramble for locks, which leads to the herding effect.
In order to solve the above problem, we redesigned it.
Version 2.0
In version 2.0, the temporary nodes created by each client under / exlusive_lock are ordered nodes, so that each client has its own lock node under / exlusive_lock, and the node with the first sequence number means that the corresponding client has successfully acquired the lock. The client at the back listens to the node in front of him, and after his preorder client execution is completed, he will be notified that the lock is successful. The logic is modified as follows:
Each client creates an ordered temporary node / exlusive_lock/lock_ under / exlusive_lock. After successful creation, there will be nodes under / exlusive_lock for each client, such as / exlusive_lock/lock_000000001
The client takes the child nodes under / exlusive_lock and sorts them to determine whether they are at the top of the list. If your lock node is in the first place, it means that the lock was acquired successfully, and the client executes the business logic.
If your own lock node is not in the first place, listen to your previous lock node. For example, if you lock the node lock_000000002 yourself, you will listen on lock_000000001.
The execution of the client corresponding to the current lock node (lock_000000001) is completed, and the lock is released, which will trigger the logic of the listening client (lock_000000002).
The listening client re-executes the step 2 logic to determine whether it has acquired the lock.
After such modification, each client only cares about whether its own preorder lock is released, so only one client will be notified at a time. Moreover, the execution order of all clients is the same as the order in which the locks were originally created. Two issues in version 1.0 have been solved.
Next, let's look at how the code is implemented.
LockSample class
This class is a distributed lock class, which implements two related methods of distributed locks:
1. Acquire the lock
2. Release the lock
The main program logic revolves around the implementation of these two methods, especially the logic of acquiring locks. Let's first take a look at the member variables of this class:
Private ZooKeeper zkClient;private static final String LOCK_ROOT_PATH = "/ Locks"; private static final String LOCK_NODE_NAME = "Lock_"; private String lockPath
ZkClient is defined to manipulate zookeeper.
The root path of the lock and the prefix of the self-increasing node. Here the production environment should be passed in by the client.
The path to the current lock.
Construction method public LockSample () throws IOException {zkClient= new ZooKeeper ("localhost:2181", 10000, new Watcher () {@ Override public void process (WatchedEvent event) {if (event.getState () = = Event.KeeperState.Disconnected) {System.out.println ("lost connection");}});}
Create a zkClient and also create a status snooping. This monitor can be removed, it just prints out the lost connection status.
Acquire lock implementation
The exposed method to acquire the lock is acquireLock (), and the logic is simple:
Public void acquireLock () throws InterruptedException, KeeperException {/ / create lock node createLock (); / / attempt to acquire lock attemptLock ();}
First create a lock node, and then try to get the lock. The real logic lies in these two methods.
CreateLock ()
First determine whether the root node / Locks of the lock exists, and create it if it does not exist. Then create an ordered temporary node under / Locks and set the current lock path variable lockPath.
The code is as follows:
Private void createLock () throws KeeperException, InterruptedException {/ / if the root node does not exist, create the root node Stat stat = zkClient.exists (LOCK_ROOT_PATH, false); if (stat = = null) {zkClient.create (LOCK_ROOT_PATH, new byte [0], ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT) } / / create EPHEMERAL_SEQUENTIAL type node String lockPath= zkClient.create (LOCK_ROOT_PATH + "/" + LOCK_NODE_NAME, Thread.currentThread (). GetName (). GetBytes (), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL); System.out.println (Thread.currentThread (). GetName () + "lock creation:" + lockPath); this.lockPath=lockPath;} attemptLock ()
This is the core method. The client tries to acquire the lock, which is the implementation of version 2.0 logic. Here, instead of repeating the logic, look directly at the code:
Private void attemptLock () throws KeeperException, InterruptedException {/ / get all the child nodes of Lock, sort by node sequence number List lockPaths = null; lockPaths = zkClient.getChildren (LOCK_ROOT_PATH, false); Collections.sort (lockPaths); int index = lockPaths.indexOf (lockPath.substring (LOCK_ROOT_PATH.length () + 1)) / / if lockPath is the node with the lowest sequence number, acquire lock if (index = = 0) {System.out.println (Thread.currentThread (). GetName () + "lock acquisition, lockPath:" + lockPath); return;} else {/ / lockPath is not the node with the lowest sequence number, listen to the previous node String preLockPath = lockPaths.get (index-1) Stat stat = zkClient.exists (LOCK_ROOT_PATH + "/" + preLockPath, watcher); / / if the previous node no longer exists, such as after the execution is completed, or the execution node is offline, re-acquire the lock if (stat = = null) {attemptLock () } else {/ / blocks the current process until preLockPath releases the lock, observed by watcher, re-acquireLock System.out.println after notifyAll ("waiting for pre-lock release, prelocakPath:" + preLockPath); synchronized (watcher) {watcher.wait ();} attemptLock ();}
Notice this line of code
Stat stat = zkClient.exists (LOCK_ROOT_PATH + "/" + preLockPath, watcher)
When we get the previous node, we also set up the listening watcher. If the front lock exists, the main thread is blocked.
The watcher definition code is as follows:
Private Watcher watcher = new Watcher () {@ Override public void process (WatchedEvent event) {System.out.println (event.getPath () + "prelock release"); synchronized (this) {notifyAll ();}
Watcher is just notifyAll, letting the main thread continue to execute so that attemptLock () is called again to try to get lock. If there is no exception, the current client should be able to successfully acquire the lock at this time.
Release lock implementation
The implementation of the release lock primitive is simple, referring to the releaseLock () method. The code is as follows:
Public void releaseLock () throws KeeperException, InterruptedException {zkClient.delete (lockPath,-1); zkClient.close (); System.out.println ("lock release:" + lockPath);}
This is the end of the code for distributed locks, and let's take a look at how the client uses it.
We create a TicketSeller class to use distributed locks as a client.
TicketSeller class sell ()
Unlocked business logic method, the code is as follows:
Private void sell () {System.out.println ("ticket sales start"); / / thread sleeps randomly for several milliseconds to simulate the real time-consuming operation int sleepMillis = (int) (Math.random () * 2000); try {/ / executes Thread.sleep (sleepMillis) for a period of time on behalf of complex logic;} catch (InterruptedException e) {e.printStackTrace () } System.out.println ("ticket sales is over");}
Just for demonstration purposes, sleep took a while.
SellTicketWithLock ()
In this method, the business logic is executed after locking, the code is as follows:
Public void sellTicketWithLock () throws KeeperException, InterruptedException, IOException {LockSample lock = new LockSample (); lock.acquireLock (); sell (); lock.releaseLock ();} Test entry
Next, let's write a main function to test:
Public static void main (String [] args) throws KeeperException, InterruptedException, IOException {TicketSeller ticketSeller = new TicketSeller (); for (int iTuno)
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.