zookeeper 分布式锁

锁原理:

1、首先要创建一个锁的根节点,比如/mylock。


2、想要获取锁的客户端在锁的根节点下面创建znode,作为/mylock的子节点,节点的类型要选择CreateMode.PERSISTENT_SEQUENTIAL,节点的名字最好用uuid(至于为什么用uuid我后面会讲,先说一下~如果不这么做在某种情况下会发生死锁,这一点我看了很多国内朋友自己的实现,都没有考虑到这一层,这也是我为什么不建议大家自己去封装这种锁,因为它确实很复杂),假设目前同时有3个客户端想要获得锁,那么/mylock下的目录应该是这个样子的。

xxx-lock-0000000001,xxx-lock-0000000002,xxx-lock-0000000003

xxx为uuid , 0000000001,0000000002,0000000003 是zook服务端自动生成的自增数字。


3、当前客户端通过getChildren(/mylock)获取所有子节点列表并根据自增数字排序,然后判断一下自己创建的节点的顺序是不是在列表当中最小的,如果是 那么获取到锁,如果不是,那么获取自己的前一个节点,并设置监听这个节点的变化,当节点变化时重新执行步骤3 直到自己是编号最小的一个为止。

举例:假设当前客户端创建的节点是0000000002,因为它的编号不是最小的,所以获取不到锁,那么它就找到它前面的一个节点0000000001 并对它设置监听。


4、释放锁,当前获得锁的客户端在操作完成后删除自己创建的节点,这样会激发zook的事件给其它客户端知道,这样其它客户端会重新执行(步骤3)。

举例:加入客户端0000000001获取到锁,然后客户端0000000002加入进来获取锁,发现自己不是编号最小的,那么它会监听它前面节点的事件(0000000001的事件)然后执行步骤(3),当客户端0000000001操作完成后删除自己的节点,这时zook服务端会发送事件,这时客户端0000000002会接收到该事件,然后重复步骤3直到获取到锁)


上面的步骤实现了一个有序锁,也就是先进入等待锁的客户端在锁可用时先获得锁。

如果想要实现一个随机锁,那么只需要把PERSISTENT_SEQUENTIAL换成一个随机数即可。


简单示例:

<dependency>  
    <groupId>org.apache.zookeeper</groupId>  
    <artifactId>zookeeper</artifactId>  
    <version>3.4.8</version>  
</dependency>  
  
<dependency>  
    <groupId>org.apache.curator</groupId>  
    <artifactId>curator-recipes</artifactId>  
    <version>2.9.1</version>  
</dependency>  
  
<dependency>  
    <groupId>org.apache.curator</groupId>  
    <artifactId>curator-client</artifactId>  
    <version>2.9.1</version>  
</dependency>  


public class CuratorDemo {  
  
    public static void main(String[] args) throws Exception {  
        for (int i = 0; i < 10; i++) {  
            //启动10个线程模拟多个客户端  
            Jvmlock jl = new Jvmlock(i);  
            new Thread(jl).start();  
            //这里加上300毫秒是为了让线程按顺序启动,不然有可能4号线程比3号线程先启动了,这样测试就不准了。  
            Thread.sleep(300);  
        }  
    }  
      
    public static class Jvmlock implements Runnable{  
          
        private int num;  
        public Jvmlock(int num) {  
            this.num = num;  
        }  
          
        @Override  
        public void run() {  
            RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000,3);  
            CuratorFramework client = CuratorFrameworkFactory  
                    .newClient("192.168.142.128:2181", retryPolicy);  
            client.start();  
              
            InterProcessMutex lock = new InterProcessMutex(client,  
                    "/mylock");  
            try {  
                System.out.println("我是第" + num + "号线程,我开始获取锁");  
                lock.acquire();  
                System.out.println("我是第" + num + "号线程,我已经获取锁");  
                Thread.sleep(10000);  
            } catch (Exception e) {  
                e.printStackTrace();  
            } finally {  
                try {  
                    lock.release();  
                } catch (Exception e) {  
                    e.printStackTrace();  
                }  
            }  
            client.close();  
        }  
    }  
  
}  

详情请看:

http://blog.csdn.net/nimasike/article/details/51567653


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值