zoukankan      html  css  js  c++  java
  • Zookeeper-分布式锁代码实现

    Zookeeper实现分布式锁,下面接着记录下代码实现,代码部分参考某网络课程,其他部分参考文末博文。

    实现思路

    以下是大方向的实现思路,相比上篇区分读写请求,这里代码实现是不区分读写的,直接只比较/shared节点下临时有序节点的序号,最小的将获取到锁,并且设置的Watcher监听也只会监听前一个序号对应的节点。

    代码实现

    自定义一个类,实现Watcher接口,重写里面的回调函数process(WatchedEvent event),根据回调参数event返回的不同结果,实行不同的逻辑处理。

    ZKDistributedLock类

    package com.boe.lock;
    
    import org.apache.log4j.BasicConfigurator;
    import org.apache.log4j.Logger;
    import org.apache.zookeeper.*;
    import org.apache.zookeeper.data.Stat;
    
    import java.io.IOException;
    import java.util.Collections;
    import java.util.List;
    import java.util.concurrent.CountDownLatch;
    
    /**
     * 自定义分布式锁
     */
    public class ZKDistributedLock implements Watcher {
    
        private int threadId;
        //形如[第i个线程]
        private String THREAD_FLAG;
        //连接zookeeper服务器用
        private ZooKeeper zk = null;
    
        //分布式锁相关父节点路径
        private static final String GROUP_PATH = "/shared";
        //分布式锁相关的子节点路径
        private static final String SUB_PATH = "/shared/node";
    
        //当前临时顺序子节点
        private String currentEphemeralNode;
        //比当前临时顺序子节点序号小的前面那个子节点
        private String preEphemeralNode;
    
    
        //打印日志相关
        private static final Logger logger = Logger.getLogger(ZKDistributedLock.class);
    
        //使用闭锁,必须计数为0,await方法才解除阻塞继续向下执行
        private CountDownLatch connectCountDownLatch = new CountDownLatch(1);
    
        //使用闭锁,应对10个线程都抢到锁并处理完逻辑后,打印结果
        public static final CountDownLatch threadCountDownLatch = new CountDownLatch(5);
    
        //记录process方法使用次数
        private int count=0;
    
    
        /**
         * 构造方法
         */
        public ZKDistributedLock(int threadId) {
            this.threadId = threadId;
            THREAD_FLAG = "[第" + threadId + "个线程]";
        }
    
    
        /**
         * 回调函数,返回连接结果
         *
         * @param event
         */
        @Override
        public void process(WatchedEvent event) {
            if (event == null) {
                return;
            }
            //一种跟连接相关
            Event.KeeperState connectState = event.getState();
            //一种跟事件类型相关,如获取锁的线程删除临时节点,释放锁
            Event.EventType eventType = event.getType();
            //必须同时满足两个条件,闭锁才能减1
            if (connectState == Event.KeeperState.SyncConnected && eventType == Event.EventType.None) {
                //连接zookeeper成功
                logger.info(THREAD_FLAG + "连接zookeeper服务器成功");
                //闭锁减一
                connectCountDownLatch.countDown();
            } else if (event.getType() == Event.EventType.NodeDeleted && event.getPath().equals(preEphemeralNode)) {
                logger.info(THREAD_FLAG+"当前节点"+currentEphemeralNode+"前面节点"+preEphemeralNode+"被删除");
                try {
                    if (isMinPath()) {
                        getDistributedLock();
                    }
                } catch (KeeperException e) {
                    e.printStackTrace();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            } else if (Event.KeeperState.Disconnected == connectState) {
                logger.info(THREAD_FLAG + "与zookeeper服务器断开连接");
            } else if (Event.KeeperState.AuthFailed == connectState) {
                logger.info(THREAD_FLAG + "权限检查失败");
            } else if (Event.KeeperState.Expired == connectState) {
                logger.info(THREAD_FLAG + "与zookeeper服务器会话失效");
            }
    
            System.out.println(THREAD_FLAG+"执行"+(++count)+"次process方法");
    
    
        }
    
        /**
         * 创建跟zookeeper服务器的连接
         *
         * @param connectAddress zookeeper服务器地址
         * @param sessionTimeout session超时时间
         */
        public void createConnection(String connectAddress, int sessionTimeout) throws IOException, InterruptedException {
            zk = new ZooKeeper(connectAddress, sessionTimeout, this);
            System.out.println(THREAD_FLAG+"开始连接zookeeper...");
            connectCountDownLatch.await();
            //回调函数闭锁归零,才打印
            //System.out.println("连接zookeeper成功!");
        }
    
        /**
         * 创建组路径
         */
        public void createGroupPath() throws KeeperException, InterruptedException {
            //zookeeper中不存在就创建
            if (zk.exists(GROUP_PATH, true) == null) {
                String createdPath = zk.create(GROUP_PATH, null, ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
                logger.warn(THREAD_FLAG + "创建" + createdPath + "成功");
            }
    
        }
    
        /**
         * 尝试获取锁
         */
        public void grabLock() throws KeeperException, InterruptedException {
            //先创建临时节点
            currentEphemeralNode = zk.create(SUB_PATH, null, ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
            logger.info(THREAD_FLAG + "创建" + currentEphemeralNode+"临时顺序节点");
            //检查是否可以获取锁
            if (isMinPath()) {
                //如果是最小序号的节点,获取锁
                getDistributedLock();
            }
        }
    
    
        /**
         * 判断当前临时节点是否是最小序号的,如果不是最小节点,获取前面节点,并且设置监听
         * @return
         */
        private boolean isMinPath() throws KeeperException, InterruptedException {
            //获取所有节点,并且排序
            List<String> nodes = zk.getChildren(GROUP_PATH, false);
            Collections.sort(nodes);
            //判断当前创建的临时顺序节点是否是序号为0的,是0就是最小,可以获取锁
            String node = currentEphemeralNode.substring(GROUP_PATH.length() + 1);//形如node0000?
            int index = nodes.indexOf(node);
            switch (index) {
                case -1:
                    logger.info(THREAD_FLAG + "本节点不存在了" + node);
                    return false;
                case 0:
                    logger.info(THREAD_FLAG +node+"就是最小的子节点");
                    return true;
                default:
                    try {
                        //找到比自己序号小1的临时节点
                        preEphemeralNode = GROUP_PATH + "/" + nodes.get(index - 1);
                        logger.info(THREAD_FLAG + currentEphemeralNode + "前面的节点是" + preEphemeralNode);
                        //通过查询节点数据来设置监听
                        zk.getData(preEphemeralNode, true, new Stat());
                        return false;
                    } catch (KeeperException e) {
                        if (zk.exists(preEphemeralNode, false) == null) {
                            logger.info(THREAD_FLAG + "排在" + currentEphemeralNode + "前面的子节点" + preEphemeralNode + "不存在");
                            //出现异常,再次调用
                            return isMinPath();
                        } else {
                            throw e;
                        }
                    }
            }
        }
    
        /**
         * 获取锁成功
         */
        private void getDistributedLock() throws KeeperException, InterruptedException {
            if (zk.exists(currentEphemeralNode, false) == null) {
                logger.info(THREAD_FLAG + "节点不存在");
                return;
            }
            logger.info(THREAD_FLAG + "获取锁成功");
            Thread.sleep(2000);
            System.out.println(THREAD_FLAG + "干完活了~~~");
            //删除临时节点,不考虑版本
            zk.delete(currentEphemeralNode, -1);
            logger.info(THREAD_FLAG+"节点"+currentEphemeralNode+"已删除");
            //释放与zookeeper服务器的连接
            if (zk != null) {
                zk.close();
            }
            logger.info(THREAD_FLAG + "释放了与zookeeper的连接");
    
            //闭锁减1
            threadCountDownLatch.countDown();
    
        }
    
    }
    

    代码实现具体逻辑图,如下图所示,需要区分两种情况,一种是当前线程创建的节点就是序号最小的,一种是序号非最小的。

    ZKDistributedLock类实现了Watcher接口,需重写proces方法,每个线程会执行代码里process方法2次,一次为连接zookeeper服务器成功会执行一次,一次为前一个设置Watcher监听的节点被删除后,监听到后会再次执行一次process方法,并且在process方法里完成判断是否序号最小节点(isMinPath方法)和抢占锁(getDistributedLock方法)业务逻辑。

    另外,刚开始创建序号最小节点的线程,会先创建/shared父节点,因此它也会执行两次process方法,虽然也是两次但是和其他序号的子节点是走不同的路线。它会执行在grabLock方法里完成判断是否序号最小节点(isMinPath方法)和抢占锁(getDistributedLock方法)业务逻辑。

    再写一个测试类,在main方法里创建5个线程,模拟5个client连接zookeeper服务器创建临时有序节点,完成抢占锁的逻辑。

    TestZKDistributedLock类

    package com.boe.lock;
    
    import org.apache.log4j.BasicConfigurator;
    import org.apache.log4j.Logger;
    
    import java.util.concurrent.CountDownLatch;
    
    /**
     * 测试zookeeper分布式锁
     */
    public class TestZKDistributedLock {
    
        private int threadId;
        //连接zookeeper的地址
        private static final String CONNECT_ADDRESS="node01:2181,node02:2181,node03:2181";
        private static final int SESSION_TIMEOUT=30000;
    
    
        //打印日志相关
        private static final Logger logger=Logger.getLogger(TestZKDistributedLock.class);
    
        //主方法
        public static void main(String[] args) {
            BasicConfigurator.configure();
            //启动5个线程,模拟5个client连接zookeeper服务器,创建临时有序节点并抢占锁
            for (int i = 0; i < 5; i++) {
                //线程数从1开始
                int threadId=i+1;
                //启动线程
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            //创建跟zookeeper服务器的连接
                            ZKDistributedLock lock=new ZKDistributedLock(threadId);
                            lock.createConnection(CONNECT_ADDRESS,SESSION_TIMEOUT);
                            System.out.println("[第"+threadId+"个线程]+"连接成功,准备开始创建临时有序节点和抢占锁");
                            //首先确认是否创建父节点/Shared,只能有一个线程创建成功,zookeeper只会让一个线程创建成功
                            //哪个线程先执行到这里,哪个线程就创建父节点
                            synchronized (ZKDistributedLock.threadCountDownLatch){
                                lock.createGroupPath();
                            }
                            //尝试获取分布式锁
                            lock.grabLock();
                        } catch (Exception e) {
                            logger.error("[第"+threadId+"个线程]抛出异常");
                            e.printStackTrace();
                        }
                    }
                }).start();
            }
            //循环结束,提示所有线程执行完成
            try {
                ZKDistributedLock.threadCountDownLatch.await();
                logger.info("所有线程创建临时有序节点完成,并完成抢占锁后执行业务逻辑");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
    
        }
    }
    

    测试结果

    启动zookeeper服务器,IDEA中本地运行,通过查看控制台日志记录,以及连接zookeeper服务器查看节点下子节点情况,发现正常的执行了创建临时有序节点、判断是否是最小节点、在前一个节点设置Watcher监听、抢占锁、释放锁的业务。

    (1)IDEA中控制台中结果

    # 模拟5个client连接zookeeper服务器
    [第5个线程]开始连接zookeeper...
    [第1个线程]开始连接zookeeper...
    [第2个线程]开始连接zookeeper...
    [第4个线程]开始连接zookeeper...
    [第3个线程]开始连接zookeeper...
    # 5个线程均连接成功,都会执行一次process方法
    2020-08-30 14:50:02 [ INFO] - com.kaikeba.lock.ZKDistributedLock -ZKDistributedLock.java(74) -[第5个线程]连接zookeeper服务器成功
    264 [Thread-4-EventThread] INFO com.kaikeba.lock.ZKDistributedLock  - [第5个线程]连接zookeeper服务器成功
    [第5个线程]执行1次process方法
    [第5个线程]连接成功,准备开始创建临时有序节点和抢占锁
    2020-08-30 14:50:02 [ INFO] - com.kaikeba.lock.ZKDistributedLock -ZKDistributedLock.java(74) -[第3个线程]连接zookeeper服务器成功
    264 [Thread-2-EventThread] INFO com.kaikeba.lock.ZKDistributedLock  - [第3个线程]连接zookeeper服务器成功
    [第3个线程]执行1次process方法
    [第3个线程]连接成功,准备开始创建临时有序节点和抢占锁
    2020-08-30 14:50:02 [ INFO] - com.kaikeba.lock.ZKDistributedLock -ZKDistributedLock.java(74) -[第4个线程]连接zookeeper服务器成功
    264 [Thread-3-EventThread] INFO com.kaikeba.lock.ZKDistributedLock  - [第4个线程]连接zookeeper服务器成功
    [第4个线程]执行1次process方法
    [第4个线程]连接成功,准备开始创建临时有序节点和抢占锁
    2020-08-30 14:50:02 [ INFO] - com.kaikeba.lock.ZKDistributedLock -ZKDistributedLock.java(74) -[第2个线程]连接zookeeper服务器成功
    264 [Thread-1-EventThread] INFO com.kaikeba.lock.ZKDistributedLock  - [第2个线程]连接zookeeper服务器成功
    [第2个线程]执行1次process方法
    [第2个线程]连接成功,准备开始创建临时有序节点和抢占锁
    2020-08-30 14:50:02 [ INFO] - com.kaikeba.lock.ZKDistributedLock -ZKDistributedLock.java(74) -[第1个线程]连接zookeeper服务器成功
    264 [Thread-0-EventThread] INFO com.kaikeba.lock.ZKDistributedLock  - [第1个线程]连接zookeeper服务器成功
    [第1个线程]执行1次process方法
    [第1个线程]连接成功,准备开始创建临时有序节点和抢占锁
    # 创建/shared父节点的线程,会再次执行一次process方法,它也将创建最小序号的临时有序节点
    [第5个线程]执行2次process方法
    323 [Thread-4-SendThread(node02:2181)] DEBUG org.apache.zookeeper.ClientCnxn  - Reading reply sessionid:0x2743d37f9940019, packet:: clientPath:null serverPath:null finished:false header:: 2,1  replyHeader:: 2,257698038051,0  request:: '/shared,,v{s{31,s{'world,'anyone}}},0  response:: '/shared 
    2020-08-30 14:50:02 [ WARN] - com.kaikeba.lock.ZKDistributedLock -ZKDistributedLock.java(122) -[第5个线程]创建/shared成功
    323 [Thread-4] WARN com.kaikeba.lock.ZKDistributedLock  - [第5个线程]创建/shared成功
    340 [Thread-4-SendThread(node02:2181)] DEBUG org.apache.zookeeper.ClientCnxn  - Reading reply sessionid:0x2743d37f9940019, packet:: clientPath:null serverPath:null finished:false header:: 3,1  replyHeader:: 3,257698038052,0  request:: '/shared/node,,v{s{31,s{'world,'anyone}}},3  response:: '/shared/node0000000000 
    2020-08-30 14:50:02 [ INFO] - com.kaikeba.lock.ZKDistributedLock -ZKDistributedLock.java(133) -[第5个线程]创建/shared/node0000000000临时顺序节点
    340 [Thread-4] INFO com.kaikeba.lock.ZKDistributedLock  - [第5个线程]创建/shared/node0000000000临时顺序节点
    344 [Thread-0-SendThread(node02:2181)] DEBUG org.apache.zookeeper.ClientCnxn  - Reading reply sessionid:0x2743d37f9940016, packet:: clientPath:null serverPath:null finished:false header:: 1,3  replyHeader:: 1,257698038052,0  request:: '/shared,T  response:: s{257698038051,257698038051,1598770202917,1598770202917,0,1,0,0,0,1,257698038052} 
    364 [Thread-4-SendThread(node02:2181)] DEBUG org.apache.zookeeper.ClientCnxn  - Reading reply sessionid:0x2743d37f9940019, packet:: clientPath:null serverPath:null finished:false header:: 4,8  replyHeader:: 4,257698038052,0  request:: '/shared,F  response:: v{'node0000000000} 
    2020-08-30 14:50:02 [ INFO] - com.kaikeba.lock.ZKDistributedLock -ZKDistributedLock.java(158) -[第5个线程]node0000000000就是最小的子节点
    365 [Thread-4] INFO com.kaikeba.lock.ZKDistributedLock  - [第5个线程]node0000000000就是最小的子节点
    369 [Thread-0-SendThread(node02:2181)] DEBUG org.apache.zookeeper.ClientCnxn  - Reading reply sessionid:0x2743d37f9940016, packet:: clientPath:null serverPath:null finished:false header:: 2,1  replyHeader:: 2,257698038053,0  request:: '/shared/node,,v{s{31,s{'world,'anyone}}},3  response:: '/shared/node0000000001 
    2020-08-30 14:50:02 [ INFO] - com.kaikeba.lock.ZKDistributedLock -ZKDistributedLock.java(133) -[第1个线程]创建/shared/node0000000001临时顺序节点
    369 [Thread-0] INFO com.kaikeba.lock.ZKDistributedLock  - [第1个线程]创建/shared/node0000000001临时顺序节点
    369 [Thread-4-SendThread(node02:2181)] DEBUG org.apache.zookeeper.ClientCnxn  - Reading reply sessionid:0x2743d37f9940019, packet:: clientPath:null serverPath:null finished:false header:: 5,3  replyHeader:: 5,257698038053,0  request:: '/shared/node0000000000,F  response:: s{257698038052,257698038052,1598770202930,1598770202930,0,0,0,176833595994013721,0,0,257698038052} 
    369 [Thread-1-SendThread(node02:2181)] DEBUG org.apache.zookeeper.ClientCnxn  - Reading reply sessionid:0x2743d37f9940018, packet:: clientPath:null serverPath:null finished:false header:: 1,3  replyHeader:: 1,257698038053,0  request:: '/shared,T  response:: s{257698038051,257698038051,1598770202917,1598770202917,0,2,0,0,0,2,257698038053} 
    2020-08-30 14:50:02 [ INFO] - com.kaikeba.lock.ZKDistributedLock -ZKDistributedLock.java(188) -[第5个线程]获取锁成功
    370 [Thread-4] INFO com.kaikeba.lock.ZKDistributedLock  - [第5个线程]获取锁成功
    376 [Thread-3-SendThread(node03:2181)] DEBUG org.apache.zookeeper.ClientCnxn  - Reading reply sessionid:0x3743d37f63e001a, packet:: clientPath:null serverPath:null finished:false header:: 1,3  replyHeader:: 1,257698038053,0  request:: '/shared,T  response:: s{257698038051,257698038051,1598770202917,1598770202917,0,2,0,0,0,2,257698038053} 
    380 [Thread-0-SendThread(node02:2181)] DEBUG org.apache.zookeeper.ClientCnxn  - Reading reply sessionid:0x2743d37f9940016, packet:: clientPath:null serverPath:null finished:false header:: 3,8  replyHeader:: 3,257698038053,0  request:: '/shared,F  response:: v{'node0000000000,'node0000000001} 
    2020-08-30 14:50:02 [ INFO] - com.kaikeba.lock.ZKDistributedLock -ZKDistributedLock.java(164) -[第1个线程]/shared/node0000000001前面的节点是/shared/node0000000000
    380 [Thread-0] INFO com.kaikeba.lock.ZKDistributedLock  - [第1个线程]/shared/node0000000001前面的节点是/shared/node0000000000
    383 [Thread-1-SendThread(node02:2181)] DEBUG org.apache.zookeeper.ClientCnxn  - Reading reply sessionid:0x2743d37f9940018, packet:: clientPath:null serverPath:null finished:false header:: 2,1  replyHeader:: 2,257698038054,0  request:: '/shared/node,,v{s{31,s{'world,'anyone}}},3  response:: '/shared/node0000000002 
    2020-08-30 14:50:02 [ INFO] - com.kaikeba.lock.ZKDistributedLock -ZKDistributedLock.java(133) -[第2个线程]创建/shared/node0000000002临时顺序节点
    383 [Thread-1] INFO com.kaikeba.lock.ZKDistributedLock  - [第2个线程]创建/shared/node0000000002临时顺序节点
    384 [Thread-2-SendThread(node02:2181)] DEBUG org.apache.zookeeper.ClientCnxn  - Reading reply sessionid:0x2743d37f9940017, packet:: clientPath:null serverPath:null finished:false header:: 1,3  replyHeader:: 1,257698038054,0  request:: '/shared,T  response:: s{257698038051,257698038051,1598770202917,1598770202917,0,3,0,0,0,3,257698038054} 
    391 [Thread-1-SendThread(node02:2181)] DEBUG org.apache.zookeeper.ClientCnxn  - Reading reply sessionid:0x2743d37f9940018, packet:: clientPath:null serverPath:null finished:false header:: 3,8  replyHeader:: 3,257698038055,0  request:: '/shared,F  response:: v{'node0000000002,'node0000000003,'node0000000000,'node0000000001} 
    2020-08-30 14:50:02 [ INFO] - com.kaikeba.lock.ZKDistributedLock -ZKDistributedLock.java(164) -[第2个线程]/shared/node0000000002前面的节点是/shared/node0000000001
    391 [Thread-1] INFO com.kaikeba.lock.ZKDistributedLock  - [第2个线程]/shared/node0000000002前面的节点是/shared/node0000000001
    392 [Thread-0-SendThread(node02:2181)] DEBUG org.apache.zookeeper.ClientCnxn  - Reading reply sessionid:0x2743d37f9940016, packet:: clientPath:null serverPath:null finished:false header:: 4,4  replyHeader:: 4,257698038055,0  request:: '/shared/node0000000000,T  response:: ,s{257698038052,257698038052,1598770202930,1598770202930,0,0,0,176833595994013721,0,0,257698038052} 
    397 [Thread-3-SendThread(node03:2181)] DEBUG org.apache.zookeeper.ClientCnxn  - Reading reply sessionid:0x3743d37f63e001a, packet:: clientPath:null serverPath:null finished:false header:: 2,1  replyHeader:: 2,257698038055,0  request:: '/shared/node,,v{s{31,s{'world,'anyone}}},3  response:: '/shared/node0000000003 
    2020-08-30 14:50:02 [ INFO] - com.kaikeba.lock.ZKDistributedLock -ZKDistributedLock.java(133) -[第4个线程]创建/shared/node0000000003临时顺序节点
    397 [Thread-3] INFO com.kaikeba.lock.ZKDistributedLock  - [第4个线程]创建/shared/node0000000003临时顺序节点
    400 [Thread-1-SendThread(node02:2181)] DEBUG org.apache.zookeeper.ClientCnxn  - Reading reply sessionid:0x2743d37f9940018, packet:: clientPath:null serverPath:null finished:false header:: 4,4  replyHeader:: 4,257698038056,0  request:: '/shared/node0000000001,T  response:: ,s{257698038053,257698038053,1598770202953,1598770202953,0,0,0,176833595994013718,0,0,257698038053} 
    400 [Thread-2-SendThread(node02:2181)] DEBUG org.apache.zookeeper.ClientCnxn  - Reading reply sessionid:0x2743d37f9940017, packet:: clientPath:null serverPath:null finished:false header:: 2,1  replyHeader:: 2,257698038056,0  request:: '/shared/node,,v{s{31,s{'world,'anyone}}},3  response:: '/shared/node0000000004 
    2020-08-30 14:50:02 [ INFO] - com.kaikeba.lock.ZKDistributedLock -ZKDistributedLock.java(133) -[第3个线程]创建/shared/node0000000004临时顺序节点
    400 [Thread-2] INFO com.kaikeba.lock.ZKDistributedLock  - [第3个线程]创建/shared/node0000000004临时顺序节点
    404 [Thread-3-SendThread(node03:2181)] DEBUG org.apache.zookeeper.ClientCnxn  - Reading reply sessionid:0x3743d37f63e001a, packet:: clientPath:null serverPath:null finished:false header:: 3,8  replyHeader:: 3,257698038055,0  request:: '/shared,F  response:: v{'node0000000002,'node0000000003,'node0000000000,'node0000000001} 
    2020-08-30 14:50:02 [ INFO] - com.kaikeba.lock.ZKDistributedLock -ZKDistributedLock.java(164) -[第4个线程]/shared/node0000000003前面的节点是/shared/node0000000002
    404 [Thread-3] INFO com.kaikeba.lock.ZKDistributedLock  - [第4个线程]/shared/node0000000003前面的节点是/shared/node0000000002
    408 [Thread-3-SendThread(node03:2181)] DEBUG org.apache.zookeeper.ClientCnxn  - Reading reply sessionid:0x3743d37f63e001a, packet:: clientPath:null serverPath:null finished:false header:: 4,4  replyHeader:: 4,257698038056,0  request:: '/shared/node0000000002,T  response:: ,s{257698038054,257698038054,1598770202976,1598770202976,0,0,0,176833595994013720,0,0,257698038054} 
    408 [Thread-2-SendThread(node02:2181)] DEBUG org.apache.zookeeper.ClientCnxn  - Reading reply sessionid:0x2743d37f9940017, packet:: clientPath:null serverPath:null finished:false header:: 3,8  replyHeader:: 3,257698038056,0  request:: '/shared,F  response:: v{'node0000000002,'node0000000003,'node0000000004,'node0000000000,'node0000000001} 
    2020-08-30 14:50:02 [ INFO] - com.kaikeba.lock.ZKDistributedLock -ZKDistributedLock.java(164) -[第3个线程]/shared/node0000000004前面的节点是/shared/node0000000003
    408 [Thread-2] INFO com.kaikeba.lock.ZKDistributedLock  - [第3个线程]/shared/node0000000004前面的节点是/shared/node0000000003
    411 [Thread-2-SendThread(node02:2181)] DEBUG org.apache.zookeeper.ClientCnxn  - Reading reply sessionid:0x2743d37f9940017, packet:: clientPath:null serverPath:null finished:false header:: 4,4  replyHeader:: 4,257698038056,0  request:: '/shared/node0000000003,T  response:: ,s{257698038055,257698038055,1598770202981,1598770202981,0,0,0,248891189975973914,0,0,257698038055} 
    # 序号最小的节点对应线程执行完逻辑,将释放分布式锁
    [第5个线程]干完活了~~~
    2377 [Thread-0-SendThread(node02:2181)] DEBUG org.apache.zookeeper.ClientCnxn  - Got notification sessionid:0x2743d37f9940016
    2377 [Thread-0-SendThread(node02:2181)] DEBUG org.apache.zookeeper.ClientCnxn  - Got WatchedEvent state:SyncConnected type:NodeDeleted path:/shared/node0000000000 for sessionid 0x2743d37f9940016
    2020-08-30 14:50:04 [ INFO] - com.kaikeba.lock.ZKDistributedLock -ZKDistributedLock.java(78) -[第1个线程]当前节点/shared/node0000000001前面节点/shared/node0000000000被删除
    2378 [Thread-0-EventThread] INFO com.kaikeba.lock.ZKDistributedLock  - [第1个线程]当前节点/shared/node0000000001前面节点/shared/node0000000000被删除
    2378 [Thread-4-SendThread(node02:2181)] DEBUG org.apache.zookeeper.ClientCnxn  - Reading reply sessionid:0x2743d37f9940019, packet:: clientPath:null serverPath:null finished:false header:: 6,2  replyHeader:: 6,257698038057,0  request:: '/shared/node0000000000,-1  response:: null
    2020-08-30 14:50:04 [ INFO] - com.kaikeba.lock.ZKDistributedLock -ZKDistributedLock.java(193) -[第5个线程]节点/shared/node0000000000已删除
    2379 [Thread-4] INFO com.kaikeba.lock.ZKDistributedLock  - [第5个线程]节点/shared/node0000000000已删除
    2379 [Thread-4] DEBUG org.apache.zookeeper.ZooKeeper  - Closing session: 0x2743d37f9940019
    2379 [Thread-4] DEBUG org.apache.zookeeper.ClientCnxn  - Closing client for session: 0x2743d37f9940019
    2385 [Thread-0-SendThread(node02:2181)] DEBUG org.apache.zookeeper.ClientCnxn  - Reading reply sessionid:0x2743d37f9940016, packet:: clientPath:null serverPath:null finished:false header:: 5,8  replyHeader:: 5,257698038057,0  request:: '/shared,F  response:: v{'node0000000002,'node0000000003,'node0000000004,'node0000000001} 
    2020-08-30 14:50:04 [ INFO] - com.kaikeba.lock.ZKDistributedLock -ZKDistributedLock.java(158) -[第1个线程]node0000000001就是最小的子节点
    2385 [Thread-0-EventThread] INFO com.kaikeba.lock.ZKDistributedLock  - [第1个线程]node0000000001就是最小的子节点
    2387 [Thread-4-SendThread(node02:2181)] DEBUG org.apache.zookeeper.ClientCnxn  - Reading reply sessionid:0x2743d37f9940019, packet:: clientPath:null serverPath:null finished:false header:: 7,-11  replyHeader:: 7,257698038058,0  request:: null response:: null
    2387 [Thread-4] DEBUG org.apache.zookeeper.ClientCnxn  - Disconnecting client for session: 0x2743d37f9940019
    2020-08-30 14:50:04 [ INFO] - org.apache.zookeeper.ZooKeeper -ZooKeeper.java(693) -Session: 0x2743d37f9940019 closed
    2387 [Thread-4] INFO org.apache.zookeeper.ZooKeeper  - Session: 0x2743d37f9940019 closed
    2020-08-30 14:50:04 [ INFO] - com.kaikeba.lock.ZKDistributedLock -ZKDistributedLock.java(198) -[第5个线程]释放了与zookeeper的连接
    2388 [Thread-4] INFO com.kaikeba.lock.ZKDistributedLock  - [第5个线程]释放了与zookeeper的连接
    2020-08-30 14:50:04 [ INFO] - org.apache.zookeeper.ClientCnxn -ClientCnxn.java(522) -EventThread shut down for session: 0x2743d37f9940019
    2390 [Thread-4-EventThread] INFO org.apache.zookeeper.ClientCnxn  - EventThread shut down for session: 0x2743d37f9940019
    2393 [Thread-0-SendThread(node02:2181)] DEBUG org.apache.zookeeper.ClientCnxn  - Reading reply sessionid:0x2743d37f9940016, packet:: clientPath:null serverPath:null finished:false header:: 6,3  replyHeader:: 6,257698038058,0  request:: '/shared/node0000000001,F  response:: s{257698038053,257698038053,1598770202953,1598770202953,0,0,0,176833595994013718,0,0,257698038053} 
    2020-08-30 14:50:04 [ INFO] - com.kaikeba.lock.ZKDistributedLock -ZKDistributedLock.java(188) -[第1个线程]获取锁成功
    2394 [Thread-0-EventThread] INFO com.kaikeba.lock.ZKDistributedLock  - [第1个线程]获取锁成功
    [第1个线程]干完活了~~~
    4402 [Thread-1-SendThread(node02:2181)] DEBUG org.apache.zookeeper.ClientCnxn  - Got notification sessionid:0x2743d37f9940018
    4403 [Thread-1-SendThread(node02:2181)] DEBUG org.apache.zookeeper.ClientCnxn  - Got WatchedEvent state:SyncConnected type:NodeDeleted path:/shared/node0000000001 for sessionid 0x2743d37f9940018
    2020-08-30 14:50:06 [ INFO] - com.kaikeba.lock.ZKDistributedLock -ZKDistributedLock.java(78) -[第2个线程]当前节点/shared/node0000000002前面节点/shared/node0000000001被删除
    4403 [Thread-1-EventThread] INFO com.kaikeba.lock.ZKDistributedLock  - [第2个线程]当前节点/shared/node0000000002前面节点/shared/node0000000001被删除
    4403 [Thread-0-SendThread(node02:2181)] DEBUG org.apache.zookeeper.ClientCnxn  - Reading reply sessionid:0x2743d37f9940016, packet:: clientPath:null serverPath:null finished:false header:: 7,2  replyHeader:: 7,257698038059,0  request:: '/shared/node0000000001,-1  response:: null
    2020-08-30 14:50:06 [ INFO] - com.kaikeba.lock.ZKDistributedLock -ZKDistributedLock.java(193) -[第1个线程]节点/shared/node0000000001已删除
    4403 [Thread-0-EventThread] INFO com.kaikeba.lock.ZKDistributedLock  - [第1个线程]节点/shared/node0000000001已删除
    4404 [Thread-0-EventThread] DEBUG org.apache.zookeeper.ZooKeeper  - Closing session: 0x2743d37f9940016
    4404 [Thread-0-EventThread] DEBUG org.apache.zookeeper.ClientCnxn  - Closing client for session: 0x2743d37f9940016
    4405 [Thread-1-SendThread(node02:2181)] DEBUG org.apache.zookeeper.ClientCnxn  - Reading reply sessionid:0x2743d37f9940018, packet:: clientPath:null serverPath:null finished:false header:: 5,8  replyHeader:: 5,257698038059,0  request:: '/shared,F  response:: v{'node0000000002,'node0000000003,'node0000000004} 
    2020-08-30 14:50:06 [ INFO] - com.kaikeba.lock.ZKDistributedLock -ZKDistributedLock.java(158) -[第2个线程]node0000000002就是最小的子节点
    4406 [Thread-1-EventThread] INFO com.kaikeba.lock.ZKDistributedLock  - [第2个线程]node0000000002就是最小的子节点
    4408 [Thread-0-SendThread(node02:2181)] DEBUG org.apache.zookeeper.ClientCnxn  - Reading reply sessionid:0x2743d37f9940016, packet:: clientPath:null serverPath:null finished:false header:: 8,-11  replyHeader:: 8,257698038060,0  request:: null response:: null
    4408 [Thread-0-EventThread] DEBUG org.apache.zookeeper.ClientCnxn  - Disconnecting client for session: 0x2743d37f9940016
    2020-08-30 14:50:06 [ INFO] - org.apache.zookeeper.ZooKeeper -ZooKeeper.java(693) -Session: 0x2743d37f9940016 closed
    4408 [Thread-0-EventThread] INFO org.apache.zookeeper.ZooKeeper  - Session: 0x2743d37f9940016 closed
    2020-08-30 14:50:06 [ INFO] - com.kaikeba.lock.ZKDistributedLock -ZKDistributedLock.java(198) -[第1个线程]释放了与zookeeper的连接
    4409 [Thread-0-EventThread] INFO com.kaikeba.lock.ZKDistributedLock  - [第1个线程]释放了与zookeeper的连接
    # 刚开始不是最小序号的节点,需要在再次执行process方法里抢占锁
    [第1个线程]执行2次process方法
    2020-08-30 14:50:06 [ INFO] - org.apache.zookeeper.ClientCnxn -ClientCnxn.java(522) -EventThread shut down for session: 0x2743d37f9940016
    4409 [Thread-0-EventThread] INFO org.apache.zookeeper.ClientCnxn  - EventThread shut down for session: 0x2743d37f9940016
    4410 [Thread-1-SendThread(node02:2181)] DEBUG org.apache.zookeeper.ClientCnxn  - Reading reply sessionid:0x2743d37f9940018, packet:: clientPath:null serverPath:null finished:false header:: 6,3  replyHeader:: 6,257698038060,0  request:: '/shared/node0000000002,F  response:: s{257698038054,257698038054,1598770202976,1598770202976,0,0,0,176833595994013720,0,0,257698038054} 
    2020-08-30 14:50:06 [ INFO] - com.kaikeba.lock.ZKDistributedLock -ZKDistributedLock.java(188) -[第2个线程]获取锁成功
    4410 [Thread-1-EventThread] INFO com.kaikeba.lock.ZKDistributedLock  - [第2个线程]获取锁成功
    [第2个线程]干完活了~~~
    6414 [Thread-3-SendThread(node03:2181)] DEBUG org.apache.zookeeper.ClientCnxn  - Got notification sessionid:0x3743d37f63e001a
    6414 [Thread-3-SendThread(node03:2181)] DEBUG org.apache.zookeeper.ClientCnxn  - Got WatchedEvent state:SyncConnected type:NodeDeleted path:/shared/node0000000002 for sessionid 0x3743d37f63e001a
    6415 [Thread-1-SendThread(node02:2181)] DEBUG org.apache.zookeeper.ClientCnxn  - Reading reply sessionid:0x2743d37f9940018, packet:: clientPath:null serverPath:null finished:false header:: 7,2  replyHeader:: 7,257698038061,0  request:: '/shared/node0000000002,-1  response:: null
    2020-08-30 14:50:08 [ INFO] - com.kaikeba.lock.ZKDistributedLock -ZKDistributedLock.java(193) -[第2个线程]节点/shared/node0000000002已删除
    6415 [Thread-1-EventThread] INFO com.kaikeba.lock.ZKDistributedLock  - [第2个线程]节点/shared/node0000000002已删除
    6415 [Thread-1-EventThread] DEBUG org.apache.zookeeper.ZooKeeper  - Closing session: 0x2743d37f9940018
    6415 [Thread-1-EventThread] DEBUG org.apache.zookeeper.ClientCnxn  - Closing client for session: 0x2743d37f9940018
    2020-08-30 14:50:08 [ INFO] - com.kaikeba.lock.ZKDistributedLock -ZKDistributedLock.java(78) -[第4个线程]当前节点/shared/node0000000003前面节点/shared/node0000000002被删除
    6418 [Thread-3-EventThread] INFO com.kaikeba.lock.ZKDistributedLock  - [第4个线程]当前节点/shared/node0000000003前面节点/shared/node0000000002被删除
    6420 [Thread-1-SendThread(node02:2181)] DEBUG org.apache.zookeeper.ClientCnxn  - Reading reply sessionid:0x2743d37f9940018, packet:: clientPath:null serverPath:null finished:false header:: 8,-11  replyHeader:: 8,257698038062,0  request:: null response:: null
    6420 [Thread-1-EventThread] DEBUG org.apache.zookeeper.ClientCnxn  - Disconnecting client for session: 0x2743d37f9940018
    2020-08-30 14:50:08 [ INFO] - org.apache.zookeeper.ZooKeeper -ZooKeeper.java(693) -Session: 0x2743d37f9940018 closed
    6420 [Thread-1-EventThread] INFO org.apache.zookeeper.ZooKeeper  - Session: 0x2743d37f9940018 closed
    2020-08-30 14:50:08 [ INFO] - com.kaikeba.lock.ZKDistributedLock -ZKDistributedLock.java(198) -[第2个线程]释放了与zookeeper的连接
    6420 [Thread-1-EventThread] INFO com.kaikeba.lock.ZKDistributedLock  - [第2个线程]释放了与zookeeper的连接
    [第2个线程]执行2次process方法
    2020-08-30 14:50:08 [ INFO] - org.apache.zookeeper.ClientCnxn -ClientCnxn.java(522) -EventThread shut down for session: 0x2743d37f9940018
    6421 [Thread-1-EventThread] INFO org.apache.zookeeper.ClientCnxn  - EventThread shut down for session: 0x2743d37f9940018
    6422 [Thread-3-SendThread(node03:2181)] DEBUG org.apache.zookeeper.ClientCnxn  - Reading reply sessionid:0x3743d37f63e001a, packet:: clientPath:null serverPath:null finished:false header:: 5,8  replyHeader:: 5,257698038062,0  request:: '/shared,F  response:: v{'node0000000003,'node0000000004} 
    2020-08-30 14:50:08 [ INFO] - com.kaikeba.lock.ZKDistributedLock -ZKDistributedLock.java(158) -[第4个线程]node0000000003就是最小的子节点
    6422 [Thread-3-EventThread] INFO com.kaikeba.lock.ZKDistributedLock  - [第4个线程]node0000000003就是最小的子节点
    6425 [Thread-3-SendThread(node03:2181)] DEBUG org.apache.zookeeper.ClientCnxn  - Reading reply sessionid:0x3743d37f63e001a, packet:: clientPath:null serverPath:null finished:false header:: 6,3  replyHeader:: 6,257698038062,0  request:: '/shared/node0000000003,F  response:: s{257698038055,257698038055,1598770202981,1598770202981,0,0,0,248891189975973914,0,0,257698038055} 
    2020-08-30 14:50:08 [ INFO] - com.kaikeba.lock.ZKDistributedLock -ZKDistributedLock.java(188) -[第4个线程]获取锁成功
    6425 [Thread-3-EventThread] INFO com.kaikeba.lock.ZKDistributedLock  - [第4个线程]获取锁成功
    [第4个线程]干完活了~~~
    8433 [Thread-2-SendThread(node02:2181)] DEBUG org.apache.zookeeper.ClientCnxn  - Got notification sessionid:0x2743d37f9940017
    8434 [Thread-2-SendThread(node02:2181)] DEBUG org.apache.zookeeper.ClientCnxn  - Got WatchedEvent state:SyncConnected type:NodeDeleted path:/shared/node0000000003 for sessionid 0x2743d37f9940017
    2020-08-30 14:50:10 [ INFO] - com.kaikeba.lock.ZKDistributedLock -ZKDistributedLock.java(78) -[第3个线程]当前节点/shared/node0000000004前面节点/shared/node0000000003被删除
    8434 [Thread-2-EventThread] INFO com.kaikeba.lock.ZKDistributedLock  - [第3个线程]当前节点/shared/node0000000004前面节点/shared/node0000000003被删除
    8434 [Thread-3-SendThread(node03:2181)] DEBUG org.apache.zookeeper.ClientCnxn  - Reading reply sessionid:0x3743d37f63e001a, packet:: clientPath:null serverPath:null finished:false header:: 7,2  replyHeader:: 7,257698038063,0  request:: '/shared/node0000000003,-1  response:: null
    2020-08-30 14:50:10 [ INFO] - com.kaikeba.lock.ZKDistributedLock -ZKDistributedLock.java(193) -[第4个线程]节点/shared/node0000000003已删除
    8434 [Thread-3-EventThread] INFO com.kaikeba.lock.ZKDistributedLock  - [第4个线程]节点/shared/node0000000003已删除
    8434 [Thread-3-EventThread] DEBUG org.apache.zookeeper.ZooKeeper  - Closing session: 0x3743d37f63e001a
    8434 [Thread-3-EventThread] DEBUG org.apache.zookeeper.ClientCnxn  - Closing client for session: 0x3743d37f63e001a
    8436 [Thread-2-SendThread(node02:2181)] DEBUG org.apache.zookeeper.ClientCnxn  - Reading reply sessionid:0x2743d37f9940017, packet:: clientPath:null serverPath:null finished:false header:: 5,8  replyHeader:: 5,257698038063,0  request:: '/shared,F  response:: v{'node0000000004} 
    2020-08-30 14:50:10 [ INFO] - com.kaikeba.lock.ZKDistributedLock -ZKDistributedLock.java(158) -[第3个线程]node0000000004就是最小的子节点
    8436 [Thread-2-EventThread] INFO com.kaikeba.lock.ZKDistributedLock  - [第3个线程]node0000000004就是最小的子节点
    8439 [Thread-3-SendThread(node03:2181)] DEBUG org.apache.zookeeper.ClientCnxn  - Reading reply sessionid:0x3743d37f63e001a, packet:: clientPath:null serverPath:null finished:false header:: 8,-11  replyHeader:: 8,257698038064,0  request:: null response:: null
    8439 [Thread-3-EventThread] DEBUG org.apache.zookeeper.ClientCnxn  - Disconnecting client for session: 0x3743d37f63e001a
    8439 [Thread-2-SendThread(node02:2181)] DEBUG org.apache.zookeeper.ClientCnxn  - Reading reply sessionid:0x2743d37f9940017, packet:: clientPath:null serverPath:null finished:false header:: 6,3  replyHeader:: 6,257698038064,0  request:: '/shared/node0000000004,F  response:: s{257698038056,257698038056,1598770202989,1598770202989,0,0,0,176833595994013719,0,0,257698038056} 
    2020-08-30 14:50:10 [ INFO] - org.apache.zookeeper.ZooKeeper -ZooKeeper.java(693) -Session: 0x3743d37f63e001a closed
    8439 [Thread-3-EventThread] INFO org.apache.zookeeper.ZooKeeper  - Session: 0x3743d37f63e001a closed
    2020-08-30 14:50:10 [ INFO] - com.kaikeba.lock.ZKDistributedLock -ZKDistributedLock.java(198) -[第4个线程]释放了与zookeeper的连接
    8440 [Thread-3-EventThread] INFO com.kaikeba.lock.ZKDistributedLock  - [第4个线程]释放了与zookeeper的连接
    [第4个线程]执行2次process方法
    2020-08-30 14:50:10 [ INFO] - org.apache.zookeeper.ClientCnxn -ClientCnxn.java(522) -EventThread shut down for session: 0x3743d37f63e001a
    8440 [Thread-3-EventThread] INFO org.apache.zookeeper.ClientCnxn  - EventThread shut down for session: 0x3743d37f63e001a
    2020-08-30 14:50:10 [ INFO] - com.kaikeba.lock.ZKDistributedLock -ZKDistributedLock.java(188) -[第3个线程]获取锁成功
    8440 [Thread-2-EventThread] INFO com.kaikeba.lock.ZKDistributedLock  - [第3个线程]获取锁成功
    [第3个线程]干完活了~~~
    10452 [Thread-2-SendThread(node02:2181)] DEBUG org.apache.zookeeper.ClientCnxn  - Reading reply sessionid:0x2743d37f9940017, packet:: clientPath:null serverPath:null finished:false header:: 7,2  replyHeader:: 7,257698038065,0  request:: '/shared/node0000000004,-1  response:: null
    2020-08-30 14:50:12 [ INFO] - com.kaikeba.lock.ZKDistributedLock -ZKDistributedLock.java(193) -[第3个线程]节点/shared/node0000000004已删除
    10453 [Thread-2-EventThread] INFO com.kaikeba.lock.ZKDistributedLock  - [第3个线程]节点/shared/node0000000004已删除
    10454 [Thread-2-EventThread] DEBUG org.apache.zookeeper.ZooKeeper  - Closing session: 0x2743d37f9940017
    10454 [Thread-2-EventThread] DEBUG org.apache.zookeeper.ClientCnxn  - Closing client for session: 0x2743d37f9940017
    10468 [Thread-2-SendThread(node02:2181)] DEBUG org.apache.zookeeper.ClientCnxn  - Reading reply sessionid:0x2743d37f9940017, packet:: clientPath:null serverPath:null finished:false header:: 8,-11  replyHeader:: 8,257698038066,0  request:: null response:: null
    10468 [Thread-2-EventThread] DEBUG org.apache.zookeeper.ClientCnxn  - Disconnecting client for session: 0x2743d37f9940017
    2020-08-30 14:50:13 [ INFO] - org.apache.zookeeper.ZooKeeper -ZooKeeper.java(693) -Session: 0x2743d37f9940017 closed
    10468 [Thread-2-EventThread] INFO org.apache.zookeeper.ZooKeeper  - Session: 0x2743d37f9940017 closed
    2020-08-30 14:50:13 [ INFO] - com.kaikeba.lock.ZKDistributedLock -ZKDistributedLock.java(198) -[第3个线程]释放了与zookeeper的连接
    10468 [Thread-2-EventThread] INFO com.kaikeba.lock.ZKDistributedLock  - [第3个线程]释放了与zookeeper的连接
    [第3个线程]执行2次process方法
    2020-08-30 14:50:13 [ INFO] - org.apache.zookeeper.ClientCnxn -ClientCnxn.java(522) -EventThread shut down for session: 0x2743d37f9940017
    10469 [Thread-2-EventThread] INFO org.apache.zookeeper.ClientCnxn  - EventThread shut down for session: 0x2743d37f9940017
    2020-08-30 14:50:13 [ INFO] - com.kaikeba.lock.TestZKDistributedLock -TestZKDistributedLock.java(55) -所有线程创建临时有序节点完成,并完成抢占锁后执行业务逻辑
    10470 [main] INFO com.kaikeba.lock.TestZKDistributedLock  - 所有线程创建临时有序节点完成,并完成抢占锁后执行业务逻辑
    

    (2)连接zookeeper服务器查看子节点结果

    # IDEA中本地启动5个线程后,创建了父节点/shared,且创建了临时有序子节点
    [zk: node01:2181(CONNECTED) 104] ls /shared
    [node0000000002, node0000000003, node0000000004, node0000000000, node0000000001]
    [zk: node01:2181(CONNECTED) 105] ls /shared
    [node0000000002, node0000000003, node0000000004, node0000000000, node0000000001]
    [zk: node01:2181(CONNECTED) 106] ls /shared
    [node0000000002, node0000000003, node0000000004, node0000000000, node0000000001]
    [zk: node01:2181(CONNECTED) 107] ls /shared
    [node0000000002, node0000000003, node0000000004, node0000000001]
    [zk: node01:2181(CONNECTED) 108] ls /shared
    [node0000000002, node0000000003, node0000000004, node0000000001]
    [zk: node01:2181(CONNECTED) 109] ls /shared
    [node0000000002, node0000000003, node0000000004]
    [zk: node01:2181(CONNECTED) 110] ls /shared
    [node0000000002, node0000000003, node0000000004]
    [zk: node01:2181(CONNECTED) 111] ls /shared
    [node0000000003, node0000000004]
    [zk: node01:2181(CONNECTED) 112] ls /shared
    [node0000000003, node0000000004]
    [zk: node01:2181(CONNECTED) 113] ls /shared
    [node0000000003, node0000000004]
    [zk: node01:2181(CONNECTED) 114] ls /shared
    [node0000000004]
    [zk: node01:2181(CONNECTED) 115] ls /shared
    [node0000000004]
    [zk: node01:2181(CONNECTED) 116] ls /shared
    [node0000000004]
    [zk: node01:2181(CONNECTED) 117] ls /shared
    []
    

    子节点删除的顺序按照序号从小到大,与前文的实现思路一致。

    Watcher初识

    实现类实现了Watcher接口,参考文末博文对它进行简单了解,更加详细的说明参考文末博文。

    实现Watcher接口的类需要重写process方法,并且本文实现类ZKDistributedLock也是一个新的Watcher,它内部接口Event包含两个枚举类,一个是KeeperState,一个是EventType,在process方法中多次用到了这两个枚举类的属性进行判断。

    KeeperState代表和zookeeper连接时状态发生变化对应的通知,具体属性意思代码注释如下。

    //不再使用
    @Deprecated
    Unknown (-1),          
    //客户端与服务器器断开连接
    Disconnected (0),
    //不再使用
    @Deprecated
    NoSyncConnected (1),
    //客户端与服务器正常连接时
    SyncConnected (3),
    //身份认证失败
    AuthFailed (4),
    //则当zk集群中只有少于半数的服务器正常时,会返回这个状态给客户端,此时客户端只能处理读请求,在3.3.0版本后才支持
    ConnectedReadOnly (5),
    //服务器采用SASL做校验时
    SaslAuthenticated(6),
    //会话session失效时
    Expired (-112);
    

    EventType是znode发生变化时对应的通知类型,具体属性意思代码注释如下。

    //无
    None (-1),
    //Watcher监听的数据节点被创建时
    NodeCreated (1),
    //Watcher监听的数据节点被删除时
    NodeDeleted (2),
    //Watcher监听的数据节点内容发生变更时(无论内容数据是否变化)
    NodeDataChanged (3),
    //Watcher监听的数据节点的子节点列表发生变更时
    NodeChildrenChanged (4);
    

    以上,理解不一定正确,学习就是一个不断认识和纠错的过程,如果有误还请批评指正。

    PS:7.28是一个值得纪念的日子。

    参考博文:

    (1)《从Paxos到Zookeeper-分布式一致性原理与实践》分布式锁

    (2)https://www.jianshu.com/p/c68b6b241943 watcher机制

    (3)https://www.cnblogs.com/leesf456/p/6286827.html watcher源码一

  • 相关阅读:
    我的知识库(4) java获取页面编码(Z)
    知识库(3)JAVA 正则表达式 (超详细)
    The Struts dispatcher cannot be found. This is usually caused by using Struts tags without the associated filter. Struts
    某人总结的《英语听力的技巧 》,挺搞的
    我的知识库(5)java单例模式详解
    构建可扩展程序
    SerialPort (RS232 Serial COM Port) in C# .NET
    Python学习笔记——String、Sequences
    UI题目我的答案
    jQuery学习系列学会操纵Form表单元素(1)
  • 原文地址:https://www.cnblogs.com/youngchaolin/p/13288627.html
Copyright © 2011-2022 走看看