Zookeeper distributed lock

Source: Internet
Author: User

Abstract: Share cow original,zookeeper use,zookeeper lock in the actual project development is still very common, here we introduce zookeeper the use of distributed locks, and how we Zookeeper the principle of distributed locks. Zookeeper node understanding.

What is the use of zookeeper distributed locks? The first thing to understand is what is a lock? To give a popular example, the door is locked, the outside people can not enter, the inside of the people may come out at any time, after coming out, you can continue to lock. For example, in our project, the main supplier system lock inventory This situation, lock inventory can not let other people to modify inventory information. This is the time to use the lock. Of course, you can also use the concept of database or redis version lock, according to the version to distinguish how to lock the library.

First, let's look at the zookeeper node type.

The Zookeeper node type is divided into the following four types:

1.1.1. Node Description

public enum Createmode {        /** * The Znode is not being     automatically deleted upon client ' s disconnect.     *    /persistent (0, False, false),/** * The Znode is not being    automatically deleted upon client ' s disconnect,
   * and its name is appended with a monotonically increasing number.    *    /Persistent_sequential (2, False, True),    /** * The znode would be     deleted upon the client ' s disconnect.
   
    */    Ephemeral (1, true, false),    /**     * The Znode would be deleted upon the client's disconnect, and its name< C15/>* 'll is appended with a monotonically increasing number.     *    /Ephemeral_sequential (3, True, true);}
   


From the hierarchy of persistence:

1. Persistent node: Does not delete the node always exists.

2. Non-persistent node, in other words, temporary node, temporary node is the client connection when created, when the client hangs, the temporary node is automatically deleted.

From the sorting hierarchy:

1. Persistent and orderly.

2. Persistent disorder,

3. Temporary and orderly.

4. Temporary disorder.

It is important to note that the persistence node can create child nodes. Non-persisted nodes cannot create child nodes. Here you can use the command to test it yourself.

Non-persistent node is created when the time exists, disappear, the node is automatically deleted, so we use this feature to achieve our needs, for example, I can start the program at the specified persistent node, create temporary nodes, when the program hangs, the temporary node disappears, We can monitor the health state of a program by monitoring the collection of child nodes in the specified parent node.

1.1.2. Zookeeper distributed lock implementation

Next, on the basis of understanding nodes above, we can implement zookeeper distributed locks. How to achieve it? Ideas are as follows:

We can create a persistent node, each time we create a temporary child node in the program, and then we traverse the child nodes under the persistent node, because the temporary nodes we set are ordered. So we can lock the time, create a temporary ordered node, when we lock to complete their business, release the lock, and then, this delete temporary node, so the core point of the design is :

1. Create the parent node. Persistent node

2. Create an ordered temporary child node.

3. Delete the temporary node when the business is completed.

4. Each time you need to determine the temporary node itself, whether it is the smallest. Why should the judgment be the smallest? Because it is not the smallest, it means that there are still some nodes in the lock execution, so we cannot lock the execution of this node.

5. How do I get the node to listen and execute? Because if the node itself is minimal, it can be executed directly if it is not the smallest. To listen to whether the previous node has been deleted, if any of the previous nodes have been deleted. You can lock and execute the business code yourself.

Let's start writing our code here.

Package Com.shareniu.zktest;import Java.io.ioexception;import Java.util.collections;import java.util.List;import Java.util.concurrent.CountDownLatch; Import Org.apache.zookeeper.createmode;import Org.apache.zookeeper.keeperexception;import Org.apache.zookeeper.watchedevent;import Org.apache.zookeeper.watcher;import org.apache.zookeeper.Watcher.Event; Import Org.apache.zookeeper.watcher.event.eventtype;import Org.apache.zookeeper.watcher.event.keeperstate;import Org.apache.zookeeper.zoodefs.ids;import Org.apache.zookeeper.zookeeper;import Org.apache.zookeeper.data.Stat; public class Shareniudistributedlock implements watcher {private int threadid;//main distinguishing thread private static String prefix_of_t Hread = prefix of null;//child node private static final String Ephemeral_sequential_path = "/shareniulock/sub";//parent node private static fin Al string Parent_path = "/shareniulock";p rotected static final String connection_string = "101.201.xx.xx:2181";p rotected static final int session_timeout = 10000;//The number of threads opened private static Final int thread_num = 5;//Create temporary node itself private String selfpath;//ZK Connection object public shareniudistributedlock (int threadId)          {this.threadid = threadId;      Prefix_of_thread = "" +threadid+ "thread" ";  }private ZooKeeper ZooKeeper = null;private Countdownlatch CDL = new Countdownlatch (1);p rivate static final Countdownlatch  Threadsemaphore = new Countdownlatch (thread_num); Private String waitpath;public static void Main (string[] args) {for (int i=0; i < thread_num; i++) {fi              nal int threadId = i+1;                      New Thread () {@Override public void run () {try{                          Shareniudistributedlock dc = new Shareniudistributedlock (threadId);                          Dc.createconnection (connection_string, session_timeout); If Group_path does not exist, it can be created by a thread; synchronized (threadsemaphore) {Dc.crea Tepath (Parent_path, "The node is by thread" +ThreadId + "Create", true);                      } dc.getlock ();                      } catch (Exception e) {e.printstacktrace ();          }}}.start ();              } try {threadsemaphore.await ();          System.out.println ("All Threads run end!");          } catch (Interruptedexception e) {e.printstacktrace ();          }}/** * Implement the method in the listener to get the Watchedevent object */public void Process (Watchedevent event) {if (event = = null) {return;          } event.keeperstate keeperstate = Event.getstate ();          Event.eventtype EventType = Event.gettype ();                  if (Event.KeeperState.SyncConnected = = keeperstate) {if (Event.EventType.None = = EventType) {                  System.out.println (Prefix_of_thread + "successfully connected to ZK server");              Cdl.countdown (); }else if (event.gettype () = = Event.EventType.NodeDeleted && Event. GetPath (). Equals (Waitpath)) {try {if (Checkminpathofchilde ()) {                      Getlockbyshelf ();                  }} catch (Keeperexception e) {e.printstacktrace ();                  } catch (Interruptedexception e) {e.printstacktrace (); }}}else if (Event.KeeperState.Disconnected = = keeperstate) {System.out.println (PR          Efix_of_thread + "Disconnect from ZK server"); } else if (Event.KeeperState.AuthFailed = = keeperstate) {System.out.println (prefix_of_thread + "permission check Failed")          ;          } else if (Event.KeeperState.Expired = = keeperstate) {System.out.println (Prefix_of_thread + "session invalidated");  }}/** * Close ZK connection */public void Releaseconnection () {if (this.zookeeper! = null) {try {this.zooKeeper.close ()} catch (Interruptedexception e) {}}system.out.println (prefix_of_thread + "release Connection");} /*** * Create a connection ** @param connectstring * Connected server String * @param sessiontimeout * Time Out * @throws IOException * @throws in Terruptedexception */public void CreateConnection (String connectstring, int sessiontimeout) throws IOException, interruptedexception {zooKeeper = new ZooKeeper (connectstring, sessiontimeout, this); SYSTEM.OUT.PRINTLN ("Open connection ...");//Because opening a connection only takes one time, here in order to prevent concurrency, use the Countdownlatch object//program to wait until Cdl.countdown (); The call to the method Cdl.await ();} /** * Create node * * @param path * path * @param data * content * @param needwatch * @return * @throws keeperexce Ption * @throws interruptedexception */public boolean Createpath (string path, String data, Boolean Needwatch) throws Keeper Exception, Interruptedexception {//To determine if a node exists, do not create it. Stat exists = zookeeper.exists (path, Needwatch), if (exists = = null) {//node does not exist System.out.println (prefix_of_thread+ " Node creation succeeded, Path: "+ this.zooKeeper.create (path, data.getbytes (), Ids.open_acl_unsafe, createmode.persistent) +", content: "+ data);} return true;} /** * Get Lock * * @throws keeperexception * @throws interruptedexception */private void Getlock () throws Keeperexception, Interr uptedexception {//create temporary node Selfpath = zookeeper.create (Ephemeral_sequential_path, Null,ids.open_acl_unsafe, Createmode.persistent_sequential); SYSTEM.OUT.PRINTLN ("Create temporary node:" + Selfpath); if (Checkminpathofchilde ()) {getlockbyshelf ();}} /** * Acquired to lock * * @throws interruptedexception * @throws keeperexception */private void Getlockbyshelf () throws Keeperexcept Ion, Interruptedexception {//Get to lock start execution Code Delete node release connection if (Zookeeper.exists (This.selfpath, false) = = null) {System.out.print ln (prefix_of_thread + "This node is gone ..."); return;} else {//node exists System.out.println (Prefix_of_thread + "get lock succeeded ...");//Take a break thread.sleep (1000); System.out.println (prefix_of_thread + "Delete temporary node:" + Selfpath);//delete the time, the version is-1 is all deleted Zookeeper.delete (This.selfpath, 1 ); Releaseconnection ();//release lock other programs can continue to open the connection Cdl.countdown ();}} /** * Get Lock * * @return * @throws interruptedexception * @throws keeperexception */private boOlean Checkminpathofchilde () throws Keeperexception,interruptedexception {//Get all child nodes in parent node list<string> subNodes = Zookeeper.getchildren (Parent_path, false);//Temporary node is ordered, then sort the smallest bar collections.sort (subnodes); int index = Subnodes.indexof (Selfpath.substring (Parent_path.length () + 1)), switch (index) {case-1: {System.out.println (prefix_ Of_thread + "node is gone ..." + Selfpath); return false;} Case 0: {System.out.println (Prefix_of_thread + "can get lock execution code" + Selfpath); return true; Default: {This.waitpath = Parent_path + "/" + Subnodes.get (index-1); System.out.println (Prefix_of_thread + "front node" + Waitpath); try {zookeeper.getdata (Waitpath, True, New Stat ()); return false;} catch (Keeperexception e) {if (Zookeeper.exists (Waitpath, false) = = null) {System.out.println (Prefix_of_thread +) Node in front of this node: "+ Waitpath +" ");//recursively find it return Checkminpathofchilde ();} else {throw e;}}}}}


1.1.3. output of the program

The output of the program is as follows:

Open connection .....

Open connection .....

Open connection .....

Open connection .....

Open connection .....

"5th Thread" successfully connected to the ZK server

"5th Thread" successfully connected to the ZK server

"5th Thread" successfully connected to the ZK server

"5th Thread" successfully connected to the ZK server

"5th Thread" successfully connected to the ZK server

Create temporary node:/shareniulock/sub0000000001

The "5th thread" can get the lock execution code by itself/shareniulock/sub0000000001

Create temporary node:/shareniulock/sub0000000002

"5th Thread" gets the lock successfully ....

Node in front of "5th thread"/shareniulock/sub0000000001

Create temporary node:/shareniulock/sub0000000003

Create temporary node:/shareniulock/sub0000000004

Node in front of "5th thread"/shareniulock/sub0000000002

Node in front of "5th thread"/shareniulock/sub0000000003

Create temporary node:/shareniulock/sub0000000005

Node in front of "5th thread"/shareniulock/sub0000000004

"5th Thread" Delete temporary node:/shareniulock/sub0000000001

"5th Thread" releases the connection

The "5th thread" can get the lock execution code by itself/shareniulock/sub0000000002

"5th Thread" gets the lock successfully ....

"5th Thread" Delete temporary node:/shareniulock/sub0000000002

"5th Thread" releases the connection

The "5th thread" can get the lock execution code by itself/shareniulock/sub0000000003

"5th Thread" gets the lock successfully ....

"5th Thread" Delete temporary node:/shareniulock/sub0000000003

"5th Thread" releases the connection

The "5th thread" can get the lock execution code by itself/shareniulock/sub0000000004

"5th Thread" gets the lock successfully ....

"5th Thread" Delete temporary node:/shareniulock/sub0000000004

"5th Thread" releases the connection

The "5th thread" can get the lock execution code by itself/shareniulock/sub0000000005

"5th Thread" gets the lock successfully ....

"5th Thread" Delete temporary node:/shareniulock/sub0000000005

"5th Thread" releases the connection

1.1.4. ZK node view

Now let's take a look at the ZK node,

This proves that the node is ordered and the temporary node is deleted when the lock is released.

Share the original ( respecting the original reprint right when the first line please specify, reproduced from the share of the source of cattle http://blog.csdn.net/qq_30739519)

Zookeeper distributed lock

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.