zoukankan      html  css  js  c++  java
  • 解读curator框架实现的zookeeper的锁机制 InterProcessMultiLock

    zookeeper的分布式锁机制:

    原理:zookeeper的数据结构包含4种:

    PERSISTENT         持久化节点

    PERSISTENT_SEQUENTIAL   持久化顺序节点

    EPHEMERAL         临时节点

    EPHEMERAL_SEQUENTIAL   临时顺序节点

    顺序节点代表create后,zookeeper会自动在后面加上序号,自动加1;临时节点代表客户端连接中断后,该节点自动删除;

    利用临时顺序节点的特性,每个要获取锁的客户端(线程)在特定目录下新建一个临时顺序节点,然后比较自己的节点是否是当前路径下序号最小的节点,若是 得获取到锁,若不是,则等待;

    释放锁即删除该临时顺序节点或断开连接(临时节点自动被删除);

    curator提供了InterProcessLock接口,实现了锁机制;

    以InterProcessMultiLock实现为例,InterProcessMultiLock是多锁对象,可以对多个对象进行加锁;

    InterProcessMutex为可重入锁

    /**
     * Created by chenhao on 2018-05-10.
     */
    public class ZKLock {
        private static final String CONNECTSTRING = "192.168.0.16:2181";
        private static final String LOCKPATH = "/pay/lock";
        private static final List<String> list = new LinkedList();
        private static CuratorFramework client = CuratorFrameworkFactory.builder().connectString(CONNECTSTRING).retryPolicy(new ExponentialBackoffRetry(1000, 3)).build();
    
    
        public static void main(String[] args) throws IOException, InterruptedException {
            client.start();
            list.add(LOCKPATH);
            final InterProcessMultiLock lock = new InterProcessMultiLock(client, list);
    
            for(int i=0;i<1;i++){
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            lock.acquire();
                            SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss:SSS");
                            System.out.println(sdf.format(new Date()));
                            lock.release();
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                }).start();
            }
        }
    
    
    }
    

      

    acquire()为锁方法,这是默认不带参数的方法,当然还有超时自动放弃获取锁的入参方法;

    release()为释放锁; 

    acquire()方法

    执行过程:①使用UUID生成一个节点名称——②使用client创建生成的节点——③获取该路径下的全部节点名称——④对节点名称排序——⑤判断新建的节点索引是否为第0(第一个节点)——⑥若是则返回节点路径(获取到锁),若不是则添加zookeeper的监听器监听节点状态并阻塞指定时间(由入参决定)

    方法入口:

    执行InterProcessMutex类的

     String lockPath = internals.attemptLock(time, unit, getLockNodeBytes());

    是开始获取锁,如果获取到了则返回创建的临时顺序节点路径并保存下来(释放锁时使用);

    若获取不到则会阻塞,直到获取锁;

     ourPath = driver.createsTheLock(client, path, localLockNodeBytes);  //①②
     hasTheLock = internalLockLoop(startMillis, millisToWait, ourPath);  //③④⑤⑥

    ①使用UUID生成一个节点名称

    调用LockInternals类的ourPath = driver.createsTheLock(client, path, localLockNodeBytes);方法来生成ourPath

    接着调用了下图的方法生成了UUID,然后拼接了"-lock-"在结尾

    图中为CreateBuilderImpl类的方法

     ②使用client创建生成的节点

    使用传入client创建生成的节点,路径为上一步拼接好的

    lockNodeBytes为结点数据,没实际作用为空即可;

    ③获取该路径下的全部节点名称

     List<String> children = getSortedChildren();获取到父节点下的全部子节点名称;

    ④对节点名称排序

     

    排序时从"lock-"到节点名称结束的字符串截取为顺序节点的序号,所以节点名称必须要带有"lock-"

     ⑤判断新建的节点索引是否为第0(第一个节点)

    ourIndex来排序,判断是否为0,为0即获取到锁;

    ⑥若是则返回节点路径(获取到锁),若不是则添加zookeeper的监听器监听节点状态并阻塞指定时间(由入参决定)

     

    其它:

    "lock-"定义的地方

  • 相关阅读:
    android 源码编译 问题 列表
    springboot总结
    设计模式学习笔记
    JWT入门1
    oauth2入门github
    mybatis面试题
    shiro入门
    knife4j swagger API文档
    pahole安装(编译)
    goMySql的逆向工程
  • 原文地址:https://www.cnblogs.com/chenhao0302/p/9020169.html
Copyright © 2011-2022 走看看