<> utilize ZooKeeper Feature to implement distributed lock

​ In stand-alone applications , Multiple processes are often encountered / Threads competing for system resources , In order to maintain multiple processes / Consistency of data in the case of threads , The concept of lock is introduced into computer , thus
Ensure multi process / In the case of thread , A system resource is in a CPU There is only one process in the timeslice / Threads can access . But in the case of distributed systems , Data is no longer maintained by a single machine , It's multiple systems , Multiple machines for maintenance , According to the concept of lock in single machine , People have derived distributed locks .


ZooKeeper Open source distributed application coordination service , yes Google Of Chubby Open source implementation of , Its distributed consistency protocol is based on Paxos Algorithm based transformation , To ensure data consistency in Distributed Systems . It has many characteristics
, include zNode, Temporary node , Ordered node , Event monitoring, etc .

​ according to Zookeeper We can design a simple version of distributed lock .


The core idea is ,Zookeeper The temporary node of will be automatically deleted after the client disconnects the link , Deleting will trigger a listening event ; and Zookeeper The ordered nodes of the system can guarantee the order of the whole distributed system to acquire locks , We agree that the minimum node is the owner of the current lock . Create an ordered temporary node before attempting to acquire the lock , Then get and sort all the ordered temporary nodes , Get the smallest one , If it is the same node as the currently created node , The lock is acquired , otherwise , Get a node one level smaller than the current node according to the current node , Then register a listening event for it
, Wait until it is deleted and released .

​ code :
public class DistributeLock implements Lock, Watcher { private ZooKeeper zk =
null; //zookeeper Client instance private String ROOT_LOCK = "/locks"; // Distributed lock root private
String WAIT_LOCK; // Lock nodes that the current process needs to wait for private String CURRENT_LOCK; // Current lock private
CountDownLatch countDownLatch; public DistributeLock(){ try { zk = new
ZooKeeper("master:2181", 4000, this); // Determine whether the root node exists Stat stat =
zk.exists(ROOT_LOCK, false); if(stat == null){ // If not , Just create zk.create(ROOT_LOCK,
"0".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); } } catch
(IOException e) { e.printStackTrace(); } catch (KeeperException e) {
e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); }
} @Override public void lock() { if(this.tryLock()){
System.out.println(Thread.currentThread().getName() + "->" + CURRENT_LOCK +
"-> Lock success "); return; } waitForLock(WAIT_LOCK); // Wait to acquire lock without acquiring lock } private boolean
waitForLock(String prev){ try { Stat stat = zk.exists(prev, true);
// Set here to True, Yes prev Node listening // Because the temporary node will be automatically deleted after the client disconnects , This will trigger the listening event if(stat != null){
System.out.println(Thread.currentThread().getName() + "-> Wait for lock "+prev+"-> release ");
countDownLatch = new CountDownLatch(1); countDownLatch.await();
System.out.println(Thread.currentThread().getName() +
"-> Acquire lock "+CURRENT_LOCK+"-> success "); } } catch (KeeperException e) {
e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); }
return true; } @Override public void lockInterruptibly() throws
InterruptedException { } /** * When trying to acquire a lock , No matter what happens , First, create a temporary ordered node * And set it to the currently acquired lock *
@return */ @Override public boolean tryLock() { try { CURRENT_LOCK =
zk.create(ROOT_LOCK+"/", "0".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE,
CreateMode.EPHEMERAL_SEQUENTIAL);
System.out.println(Thread.currentThread().getName()+"->"+CURRENT_LOCK+"-> Try to compete for locks ");
List<String> childrens = zk.getChildren(ROOT_LOCK, false); SortedSet<String>
sortedSet = new TreeSet<>(); // Sort all child nodes acquired for(String child : childrens){
sortedSet.add(ROOT_LOCK+"/"+child); } String first = sortedSet.first();
// Get the smallest node SortedSet<String> lessThanMe = sortedSet.headSet(CURRENT_LOCK);
// Compare the smallest node with the one I created if(CURRENT_LOCK.equals(first)){ // Indicates that the node I create is the smallest return
true; }else{ // Otherwise, wait for the smaller node than the current node to release the lock if(!lessThanMe.isEmpty()){ WAIT_LOCK =
lessThanMe.last(); } } } catch (KeeperException e) { e.printStackTrace(); }
catch (InterruptedException e) { e.printStackTrace(); } return false; }
@Override public boolean tryLock(long time, TimeUnit unit) throws
InterruptedException { return false; } @Override public void unlock() {
System.out.println(Thread.currentThread().getName() +"-> Release lock "); try {
zk.delete(CURRENT_LOCK,-1); CURRENT_LOCK = null; zk.close(); } catch
(InterruptedException e) { e.printStackTrace(); } catch (KeeperException e) {
e.printStackTrace(); } } @Override public Condition newCondition() { return
null; } @Override public void process(WatchedEvent watchedEvent) { // Processing listening events
if(watchedEvent.getType().equals(Event.EventType.NodeDeleted)){
if(this.countDownLatch != null){ this.countDownLatch.countDown(); } } } public
static void main(String[] args) throws IOException { CountDownLatch cdLatch =
new CountDownLatch(10); for(int i=0; i<10; i++){ new Thread(() -> { try {
cdLatch.await(); DistributeLock distributeLock = new DistributeLock();
distributeLock.lock(); // Acquire lock } catch (InterruptedException e) {
e.printStackTrace(); } }, " thread "+i).start(); cdLatch.countDown(); }
System.in.read(); } }
test result

Technology
©2019-2020 Toolsou All rights reserved,
Message quality platform series | Full link troubleshooting What is? FPGA? New York Youth Project “ Recapture Wall Street ”: Safeguarding the interests of retail investors Redis Queue implementation java Second kill system , No script , It can be used in production Don't annoy the panda with any cat !「 Kung Fu Panda 」20 It's the year of man 4 blood cartoon | CPU Warfare 40 year , The real king finally appeared !JS How to operate 20 Review strategy for senior students with high marks !!! Big data tells you , How tired are Chinese women MySQL An interview is a must !