暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

分布式锁之zookeeper

xbaobao 2020-08-23
254

1.临时节点方式的ZK分布式锁,这种方实现方式适用于zkClient较少的场景,当zkClient很多时会出现羊群效应(节点变动时zkServer端需要通知每个zkClient, 此时zkServer消耗较大)

publicclass ZkLock{

     private ZooKeeper zkClient;  

     public ZkLock() {

         try {

              zkClient = new ZooKeeper("127.0.0.1:2181",30000,

              new Watcher() {        

                   publicvoid process(WatchedEvent event) {

                      

                       System.out.println("xxx");

                   }

              });

         }catch (IOException e) {

              e.printStackTrace();

         }

     }

 

     publicvoid lock() {

         try {

              while(!this.tryLock()) {

                   CountDownLatchcdl = new CountDownLatch(1);    

                   zkClient.exists("/lock", new Watcher() {

                       publicvoid process(WatchedEvent event) {

                            cdl.countDown();                  

                       }                     

                   });

                   cdl.await();

              }

         }catch (Exception e) {

              e.printStackTrace();

         }

     }

 

     privateboolean tryLock() {

         booleanlock = true;

         try {

zkClient.create("/lock", "lock".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);

         }catch (KeeperException e) {

              lock = false;

              e.printStackTrace();

         }catch (InterruptedException e) {     

              e.printStackTrace();

         }

         returnlock;

     }

 

     publicvoid unlock() {

         try {

              zkClient.delete("/lock", 0);

         }

         catch (Exception e) {   

              e.printStackTrace();

         }

     }

}

 

2.临时顺序节点方式的ZK分布式锁,这种方实现方式相对顺序节点方式,当节点变化时zkServer不用通知的每一个zkClient(zkClient监听的是子节点,不同的zkClient会监听不通的子节点,一定程度上避免了羊群效应)

publicclass ZkLock{

     private ZooKeeper zkClient;  

     private String rootNode = "/lock";

     private String currentLockNodePath;

     public ZkLock() {

         try {

              zkClient = new ZooKeeper("127.0.0.1:2181",30000,

                   new Watcher() {

                   publicvoid process(WatchedEvent event) {

                       System.out.println("xxx");

                   }

              });

         }catch (IOException e) {

              e.printStackTrace();

         }

     }

 

     publicvoid lock() {

         try {

              String currentLockNodePath = zkClient.create(

                       rootNode"/", "lock".getBytes(),

                       Ids.OPEN_ACL_UNSAFE,

                       CreateMode.EPHEMERAL_SEQUENTIAL);

             

              List<String> children  = 

                                zkClient.getChildren(rootNode, false);

              children.sort(null);

              

              String[] temps = currentLockNodePath.split("/");

              String currentLockNode = temps[temps.length - 1];

             

              //判断当前节点是否为最小节点,如果是则获取锁,若不是,

              //则找到自己的前一个节点,监听其存在状态

              intcurIndex  = children.indexOf(currentLockNode);

              if(curIndex  == 0) {

                   this.currentLockNodePath = currentLockNodePath;

              }

              else {

                   Stringprev = children.get(curIndex - 1);

                   CountDownLatchcdl = new CountDownLatch(1);

                   zkClient.exists(rootNode + "/" + prev

                       new Watcher() {

                       publicvoid process(WatchedEvent event) {

                            cdl.countDown();        

                       }                     

                   });

                   cdl.await();

              }       

         }catch (Exception e) {

              e.printStackTrace();

         }

     }

 

     publicvoid unlock() {

         try {

              zkClient.delete(currentLockNodePath, 0);

         }

         catch (Exception e) {   

              e.printStackTrace();

         }

     }

}

文章转载自xbaobao,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论