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-"定义的地方

  • 相关阅读:
    Leetcode 15 3Sum
    Leetcode 383 Ransom Note
    用i个点组成高度为不超过j的二叉树的数量。
    配对问题 小于10 1.3.5
    字符矩阵的旋转 镜面对称 1.2.2
    字符串统计 连续的某个字符的数量 1.1.4
    USACO twofive 没理解
    1002 All Roads Lead to Rome
    USACO 5.5.1 求矩形并的周长
    USACO 5.5.2 字符串的最小表示法
  • 原文地址:https://www.cnblogs.com/chenhao0302/p/9020169.html
Copyright © 2011-2022 走看看