• 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源码一

  • 相关阅读:
    给部署在openshift上的WordPress添加wptouch插件
    让你的代码符合PEP8标准——sublime text 2 安装及使用 Python Flake8 Lint 插件
    Pylot——跨平台的网站压力测试工具
    window.print打印指定div
    window.parent与window.opener的区别 转
    获取Windows Mobile开发工具
    event.srcElement
    GridView的各种用法
    JS 中document详解
    llog
  • 原文地址:https://www.cnblogs.com/youngchaolin/p/13288627.html
Copyright © 2020-2023  润新知