Simple implementation of distributed lock __zookeeper based on zookeeper

Source: Internet
Author: User
Tags zookeeper log4j

The Ephemeral_sequential type node and watcher mechanism of zookeeper are used to realize the distributed lock simply.
Main ideas:
1, open 10 threads, under the Dislocks node respectively to create a ephemeral_sequential node named sub;
2, get the Dislocks node under all the child nodes, sorting, if their own node number is minimal, then get the lock;
3, otherwise watch row in front of their nodes, listening to its deletion, into the 2nd step (re-detection of the sorting is to prevent the connection failure of the listening node, resulting in the deletion of the node);
4, delete its own sub nodes, release the connection;

Here's the Zookeeper 4 node types:

    public enum Createmode {/** * Persistent node: After the node is created, it will always exist and will not be deleted because the client session failed; */persistent  
        (0, False, false),/** * Persistent order node: the basic characteristics are consistent with the persistent node, in the process of creating a node, Zookeeper automatically appends a monotonically growing number suffix to the new node name after its name; /Persistent_sequential (2, False, True),/** * Temporary node: After the client session fails or the connection is closed, the node is automatically deleted and cannot be created under the temporary node Build child nodes, otherwise reported as follows: Org.apache.zookeeper.keeperexception$nochildrenforephemeralsexception/ephemeral (1, TR  
        UE, FALSE),/** * Temporary sequential node: The basic characteristics coincide with the temporary node, in the process of creating a node, Zookeeper automatically appends a monotonically growing number suffix to the new node name after its name;  
        Ephemeral_sequential (3, True, true);  
        private static final Logger LOG = Loggerfactory.getlogger (Createmode.class);  
        Private Boolean ephemeral;  
        private Boolean sequential;  
        private int flag;  
            Createmode (int flag, Boolean ephemeral, Boolean sequential) {This.flag = flag;  
     This.ephemeral = ephemeral;       This.sequential = sequential;  
        public Boolean isephemeral () {return ephemeral;  
        public Boolean issequential () {return sequential;  
        public int Toflag () {return flag;  
            static public createmode fromflag (int flag) throws keeperexception {switch (flag) {  
            Case 0:return Createmode.persistent;  
            Case 1:return Createmode.ephemeral;  
            Case 2:return createmode.persistent_sequential;  
            Case 3:return createmode.ephemeral_sequential;  
                Default:LOG.error ("Received a invalid flag value to convert to a createmode");  
            throw new Keeperexception.badargumentsexception ();   }  
        }  
    }
Test Code:
    Package zookeeper;  
    Import Org.slf4j.Logger;  
    Import Org.slf4j.LoggerFactory;  
    Import org.apache.zookeeper.*;  
    Import Org.apache.zookeeper.data.Stat;  
    Import java.util.List;  
    Import java.io.IOException;  
    Import java.util.Collections;  

    Import Java.util.concurrent.CountDownLatch;  
        public class Distributedlock implements watcher{private int threadId;  
        Private zookeeper ZK = null;  
        Private String Selfpath;  
        Private String Waitpath;  
        Private String Log_prefix_of_thread;  
        private static final int session_timeout = 10000;  
        private static final String Group_path = "/dislocks";  
        private static final String Sub_path = "/dislocks/sub";  

        private static final String connection_string = "192.168.*.*:2181";   
        private static final int thread_num = 10;  
        Ensure the connection zk succeeds; private Countdownlatch Connectedsemaphore = new Countdownlatch (1); //Ensure that all threads run the end; private static final Countdownlatch Threadsemaphore = new Countdownlatch (thread_num);  
        private static final Logger LOG = Loggerfactory.getlogger (Allzookeeperwatcher.class);  
            public distributedlock (int id) {this.threadid = ID;  
        Log_prefix_of_thread = "" "+threadid+" "";  
                public static void Main (string[] args) {for (int i=0; i < thread_num; i++) {  
                Final int threadId = i+1;  
                            New Thread () {@Override public void run () {try{  
                            Distributedlock dc = new Distributedlock (threadId);  
                            Dc.createconnection (connection_string, session_timeout);  
                                If Group_path does not exist, it can be created by a thread; synchronized (Threadsemaphore) { Dc.createpath (Group_path, "This node is threaded" + THREadid + "Create", true);  
                        } dc.getlock ();  
                            catch (Exception e) {log.error ("" "+threadid+ Exception thrown by" thread ");  
                        E.printstacktrace ();  
            }}.start ();  
                try {threadsemaphore.await ();  
            Log.info ("All threads run over!");  
            catch (Interruptedexception e) {e.printstacktrace (); }/** * Acquire lock * @return * * private void Getlock () throws Keepe Rexception, interruptedexception {selfpath = Zk.create (Sub_path,null, ZooDefs.Ids.OPEN_ACL_UNSAFE, Createmo De.  
            Ephemeral_sequential);  
            Log.info (log_prefix_of_thread+ "Create Lock Path:" +selfpath);  
            if (Checkminpath ()) {getlocksuccess ();  
        }/** * Create node * @param path node path * @param data initial content * @return */Public Boolean Createpath (string path, String data, Boolean Needwatch) throws Keeperexception, Interrupte dexception {if (zk.exists (path, Needwatch) ==null) {Log.info (Log_prefix_of_thread +) node is created as  
                        Work, Path: "+ this.zk.create (path, data.getbytes (), ZooDefs.Ids.OPEN_ACL_UNSAFE, Createmode.persistent) + ", cont  
            ENT: "+ data";  
        return true; /** * Create ZK connection * @param connectstring ZK server address List * @param sessiontimeout session Timeout Time */public void createconnection (String connectstring, int sessiontimeout) throws IOException, int erruptedexception {ZK = new zookeeper (connectstring, sesSiontimeout, this);  
        Connectedsemaphore.await (); /** * Acquire lock success/public void getlocksuccess () throws Keeperexception, Interruptedex ception {if (zk.exists (this.selfpath,false) = = null) {Log.error (log_prefix_of_thread+) This node has been  
                Not in ... ");  
            Return Log.info (Log_prefix_of_thread + "get lock success, work quickly.")  
            ");  
            Thread.Sleep (2000);  
            Log.info (log_prefix_of_thread + "Delete this node:" +selfpath);  
            Zk.delete (This.selfpath,-1);  
            Releaseconnection ();  
        Threadsemaphore.countdown (); /** * Close ZK/public void releaseconnection () {if (This.zk!=n  
                ull) {try {this.zk.close ();  
        catch (Interruptedexception e) {}} log.info (Log_prefix_of_thread + "release Connection");  
}        /** * Check itself is not the smallest node * @return * * public boolean Checkminpath () throws Keepe  
             Rexception, interruptedexception {list<string> subnodes = Zk.getchildren (Group_path, false);  
             Collections.sort (subnodes);  
             int index = Subnodes.indexof (selfpath.substring (Group_path.length () +1));   
                     Switch (index) {case-1:{log.error (log_prefix_of_thread+ "This node is no longer ..." +selfpath);  
                 return false;  
                     The case 0:{Log.info (log_prefix_of_thread+ "Child node, I really is the eldest brother" +selfpath);  
                 return true;  
                     } default:{This.waitpath = Group_path + "/" + Subnodes.get (index-1);  
                     Log.info (log_prefix_of_thread+ "Get the +waitpath) in the child node, in front of me;" try{Zk.getdata (Waitpath, True,New Stat ());  
                     return false;  
                             }catch (keeperexception e) {if (zk.exists (waitpath,false) = = null) {  
                             Log.info (log_prefix_of_thread+ "child node, in front of Me" +waitpath+ "has disappeared, happiness came too suddenly?");  
                         return Checkminpath ();  
                         }else{throw E; "}}}} @Override public void P  
            Rocess (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) {  
                    Log.info (Log_prefix_of_thread + "successfully connected to ZK server"); CoNnectedsemaphore.countdown ();  
                    }else if (event.gettype () = = Event.EventType.NodeDeleted && event.getpath (). Equals (Waitpath)) { Log.info (Log_prefix_of_thread + "received the information that the guy in front of me had hung up and I was not able to get out."  
                    ");  
                        try {if (Checkminpath ()) {getlocksuccess ();  
                    } catch (Keeperexception e) {e.printstacktrace ();  
                    catch (Interruptedexception e) {e.printstacktrace (); }}else if (Event.KeeperState.Disconnected = = keeperstate) {Log.inf  
            O (log_prefix_of_thread + "disconnect from ZK server");   
            else if (Event.KeeperState.AuthFailed = = keeperstate) {log.info (log_prefix_of_thread + "permission check failed");  
               else if (Event.KeeperState.Expired = = keeperstate) { Log.info (Log_prefix_of_thread + "session invalidation");   }  
        }  
    }
Log configuration file:
    # DEFAULT Log4j.rootlogger=info,console # Log INFO level and above messages to the CONSOLE # Log4j.appender.console=org.apache.log4j.consoleappender Log4j.appender.console.threshold=info log4j.a Ppender.  


    Console.layout=org.apache.log4j.patternlayout log4j.appender.console.layout.conversionpattern=%d{iso8601}-%m%n  
    Log4j.appender.commonstat=org.apache.log4j.dailyrollingfileappender Log4j.appender.commonstat.threshold=info Log4j.appender.commonstat.file=/home/zookeeper/zookeeper-test-agent/logs/test.log Log4j.appender.COMMONSTAT.Dat Epattern= '. ' YYYY-MM-DD Log4j.appender.commonstat.layout=org.apache.log4j.patternlayout log4j.appender.commonstat.layout.c ONVERSIONPATTERN=[%D{YYYY-MM-DD HH:mm:ss}]-%m%n log4j.logger.org.displaytag=warn Log4j.logger.org.apache.zo Okeeper=error Log4j.logger.org.springframework=warn Log4j.logger.org.i0itec=warn Log4j.logger.commonStat =info, Commonstat   
Run Result:
    2014-11-19 11:34:10,894-"9th thread" successfully connected ZK server 2014-11-19 11:34:10,895-"8th thread" successfully connected to ZK server 2014-11-19 11:34:1 0,894-"1th thread" successfully connected to ZK server 2014-11-19 11:34:10,894-"7th thread" successfully connected ZK server 2014-11-19 11:34:10,894-"4th thread" successfully connected ZK Server 2014-11-19 11:34:10,895-"5th thread" successfully connected ZK server 2014-11-19 11:34:10,896-"2nd thread" successfully connected ZK server 2014-11-19 1 1:34:10,894-"10th thread" successfully connected to ZK server 2014-11-19 11:34:10,894-"3rd thread" successfully connected to ZK server 2014-11-19 11:34:10,895-"6th thread" Successfully connected ZK server 2014-11-19 11:34:10,910-"Thread 9th" node created successfully, Path:/dislocks, Content: This node was created by thread 9 in 2014-11-19 11:34:10,91 2-"9th thread" create lock path:/dislocks/sub0000000000 2014-11-19 11:34:10,917-"6th thread" create lock path:/dislocks/sub0000000001 2014-1 1-19 11:34:10,917-"9th Thread" child node I was the boss./dislocks/sub0000000000 2014-11-19 11:34:10,921-"3rd thread" create Lock Path:/dislocks/sub00 00000002 2014-11-19 11:34:10,922-"6th thread" Get child node, row in front of me/dislocks/sub0000000000 2014-11-19 11:34:10,923-"9th line  
    Process to get the lock succeeded, hurriedly work. 2014-11-19 11:34:10,924-"thread 10th" Create a lock path:/dislocks/sub0000000003 2014-11-19 11:34:10,924-"3rd thread" gets the child node, in front of me/dislocks/  sub0000000001 2014-11-19 11:34:10,928-"10th thread" Get child node, row in front of me in the/dislocks/sub0000000002 2014-11-19

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.