zookeeper 分布式锁

来源:互联网 发布:如何查询数据库名称 编辑:程序博客网 时间:2024/06/13 00:45

锁原理:

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


原创粉丝点击