zookeeper(四)实现分布式锁

zookeeper实现分布式锁

实现原理

根据zookeeper结点的特点,可以通过创建临时有序节点来创建排他锁。
先进先出队列

  1. 通过getChildren获取指定根节点下的所有子节点,子节点就是任务
  2. 确定自己节点在子节点中的顺序
  3. 如果自己不是最小的子节点,那么监控比自己小的上一个子节点,否则处于等待
  4. 接收watcher通知,重复流程

引入pom

 <dependency>
      <groupId>org.apache.zookeeper</groupId>
      <artifactId>zookeeper</artifactId>
      <version>3.4.8</version>
    </dependency>
public class MyDistributeLock {

    private  ZooKeeper zooKeeper;
    private static final String ROOT_LOCKS="/LOCKS";//根节点
    private final static String CONNECTSTRING="182.92.73.88:2181";
    private final static byte[] data={1,2}; //节点的数据
    private CountDownLatch countDownLatch=new CountDownLatch(1);
    private  int sessionTimeout=5000;
    private String lockID; //记录锁节点id
    public MyDistributeLock(){
        this.zooKeeper=getInstance();
    }


    private ZooKeeper getInstance()  {

        final CountDownLatch countDownLatch1=new CountDownLatch(1);
        ZooKeeper zooKeeper= null;
        try {
            zooKeeper = new ZooKeeper(CONNECTSTRING, sessionTimeout, new Watcher() {
                @Override
                public void process(WatchedEvent event) {
                   if(event.getState()==Event.KeeperState.SyncConnected){
                       countDownLatch1.countDown();
                   }
                }
            });
        } catch (IOException e) {
            e.printStackTrace();
        }
        return zooKeeper;
    }



    public void lock() throws KeeperException, InterruptedException {
        lockID=zooKeeper.create(ROOT_LOCKS+"/",data, ZooDefs.Ids.
                OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
        List<String> childrenNodes=zooKeeper.getChildren(ROOT_LOCKS,true);//获取根节点下的所有子节点
        //排序,从小到大
        SortedSet<String> sortedSet=new TreeSet<String>();
        for(String children:childrenNodes){
            sortedSet.add(ROOT_LOCKS+"/"+children);
        }

        String first=sortedSet.first();
        if(lockID.equals(first)){
            System.out.println(Thread.currentThread().getName()+"->成功获得锁,lock节点为:["+lockID+"]");
            return;
        }

        SortedSet<String> lessThanLockId=sortedSet.headSet(lockID);
        if(!lessThanLockId.isEmpty()){
            String preid=lessThanLockId.last();
            zooKeeper.exists(preid,new MyWatcher(countDownLatch));
            countDownLatch.await(sessionTimeout, TimeUnit.MILLISECONDS);
            System.out.println(Thread.currentThread().getName()+"->成功获得锁,lock节点为:["+lockID+"]");
        }

    }
    public void unlock(){
        //System.out.println(Thread.currentThread().getName()+"->开始释放锁:["+lockID+"]");
        try {
            zooKeeper.delete(lockID,-1);
            //System.out.println("节点["+lockID+"]成功被删除");

        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (KeeperException e) {
            e.printStackTrace();
        }
    }


    public static void main(String[] args) {
        final CountDownLatch latch=new CountDownLatch(10);
        final Random random=new Random();
        for(int i=0;i<10;i++){
           new Thread(new Runnable() {
               @Override
               public void run() {
                   MyDistributeLock lock=null;
                   try {
                       lock=new MyDistributeLock();
                       latch.countDown();
                       latch.await();
                       lock.lock();
                       Thread.sleep(random.nextInt(500));
                   } catch (Exception e) {
                       e.printStackTrace();
                   } finally {
                       if(lock!=null){
                           lock.unlock();
                       }
                   }
               }

           }).start();
        }
    }

}

public class MyWatcher implements Watcher {

    CountDownLatch countDownLatch;
    public MyWatcher(CountDownLatch countDownLatch){
        this.countDownLatch=countDownLatch;
    }

    @Override
    public void process(WatchedEvent event) {
        if(event.getType()== Event.EventType.NodeDeleted){
            countDownLatch.countDown();
        }
    }
}

发布了40 篇原创文章 · 获赞 6 · 访问量 1523

猜你喜欢

转载自blog.csdn.net/qq_26737667/article/details/104405066