Big data tutorial (3.10): program of zookeeper distributed shared lock

The blogger in this section will provide you with an example of distributed shared locks, which are very important because they need to be used in many scenarios. Therefore, we must master this knowledge.

If you don't know the principle of distributed shared lock, please read the previous article first Big data tutorial (3.3): introduction to zookeeper.

Distributed shared lock case code:

package com.empire.zookeeper.test.em_zookeeper.zklock;

import java.util.Collections;
import java.util.List;
import java.util.Random;
import java.util.concurrent.CountDownLatch;

import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.Watcher.Event.EventType;
import org.apache.zookeeper.ZooDefs.Ids;
import org.apache.zookeeper.data.Stat;
import org.apache.zookeeper.ZooKeeper;

public class DistributedClientLock {
	

	// session time out
	private static final int SESSION_TIMEOUT = 2000;
	// zookeeper cluster address
	private String hosts = "centos-aaron-07:2181,centos-aaron-08:2181,centos-aaron-16:2181";
	private String groupNode = "locks";
	private String subNode = "sub";
	private boolean haveLock = false;
	private CountDownLatch connectedSemaphore = new CountDownLatch(1); 
	private ZooKeeper zk;
	// Record the path of the child node created by yourself
	private volatile String thisPath;

	/**
	 * Connect zookeeper
	 */
	public void connectZookeeper() throws Exception {
		zk = new ZooKeeper(hosts, SESSION_TIMEOUT, new Watcher() {
			public void process(WatchedEvent event) {
				try {
					connectedSemaphore.countDown(); 
					// Judge the event type. Only change events of child nodes are processed here
					if (event.getType() == EventType.NodeChildrenChanged && event.getPath().equals("/" + groupNode)) {
						//Get the child node and listen to the parent node
						List<String> childrenNodes = zk.getChildren("/" + groupNode, true);
						String thisNode = thisPath.substring(("/" + groupNode + "/").length());
						// To compare whether you are the smallest id
						Collections.sort(childrenNodes);
						if (childrenNodes.indexOf(thisNode) == 0) {
							//Access shared resources to process business, and delete lock after processing
							doSomething();
							
							//Re register a new lock
							thisPath = zk.create("/" + groupNode + "/" + subNode, null, Ids.OPEN_ACL_UNSAFE,
									CreateMode.EPHEMERAL_SEQUENTIAL);
						}
					}
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
		connectedSemaphore.await();
		Stat stat = zk.exists("/"+groupNode, false);
		System.out.println(stat==null?"not exist":"exist");
		if(stat==null) {
			String parentNodeCreate = zk.create("/"+groupNode , null, Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
		}
		
		// 1. Register a lock on zk as soon as the program comes in
		thisPath = zk.create("/" + groupNode + "/" + subNode, null, Ids.OPEN_ACL_UNSAFE,
				CreateMode.EPHEMERAL_SEQUENTIAL);

		// wait for a short time, easy to observe
		Thread.sleep(new Random().nextInt(1000));

		// Get all the child nodes from the lock parent directory of zk, and register to listen to the parent node
		List<String> childrenNodes = zk.getChildren("/" + groupNode, true);

		//If the only program competing for resources is itself, you can directly access the shared resources 
		if (childrenNodes.size() == 1) {
			doSomething();
			thisPath = zk.create("/" + groupNode + "/" + subNode, null, Ids.OPEN_ACL_UNSAFE,
					CreateMode.EPHEMERAL_SEQUENTIAL);
		}
	}

	/**
	 * Process the business logic and release the lock at the end
	 */
	private void doSomething() throws Exception {
		try {
			System.out.println("gain lock: " + thisPath);
			Thread.sleep(2000);
			// do something
		} finally {
			System.out.println("finished: " + thisPath);
			//Parameter 2: specify the version to delete, - 1 means delete all versions
			zk.delete(this.thisPath, -1);
		}
	}

	public static void main(String[] args) throws Exception {
		DistributedClientLock dl = new DistributedClientLock();
		dl.connectZookeeper();
		Thread.sleep(Long.MAX_VALUE);
	}

	
}

 

Finally, the conclusion is that the distributed shared lock actually uses the characteristics of the short-term ordered nodes of zookeeper, and can use the size of the serial number to determine the current available lock to access the shared resources.

The last message is that the above is the whole content of this blog post. If you think the blog post is not bad, please like it. If you are interested in other server technologies of the blogger or the blogger himself, please pay attention to the blogger's blog, and you are welcome to communicate with the blogger at any time.

Tags: Zookeeper Apache Java CentOS

Posted on Wed, 08 Jan 2020 08:00:27 -0800 by r3drain