最簡單分布式鎖ZK實現方案
阿新 • • 發佈:2017-10-23
zookeeper
分布式鎖簡單封裝
package com.hellojd.cloud.locks.v1; import org.apache.zookeeper.*; import java.io.IOException; import java.util.concurrent.CountDownLatch; import static org.apache.zookeeper.Watcher.Event.KeeperState.SyncConnected; /** * 最簡單分布式鎖實現方案 */ public class ZookerSession implements Watcher { private CountDownLatch countDownLatch=new CountDownLatch(1); private ZooKeeper zooKeeper; private static class Singleton{ private static ZookerSession instance; static { instance = new ZookerSession(); } public static ZookerSession getInstance(){ return instance; } } public static ZookerSession getInstance(){ return Singleton.getInstance(); } public ZookerSession() { try { this.zooKeeper = new ZooKeeper("192.168.0.10:2181",50000,this); countDownLatch.await(); System.out.println("state: "+zooKeeper.getState()); System.out.println("connection estalished!!"); } catch (IOException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } } public ZooKeeper getZooKeeper(){return this.zooKeeper;} @Override public void process(WatchedEvent event) { if(event.getState()==SyncConnected){ countDownLatch.countDown(); } } public void releaseDistributeLock(Long id){ String path ="/lock_"+id; try { zooKeeper.delete(path,-1); } catch (InterruptedException e) { e.printStackTrace(); } catch (KeeperException e) { e.printStackTrace(); } } public void acquireDistributeLock(Long id){ String path ="/lock_"+id; try { zooKeeper.create(path,null, ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL); // System.out.println("success to acquire lock "+id); } catch (KeeperException e) { //沒有獲取到鎖 int count=0; while (true){ try{ Thread.sleep(200); zooKeeper.create(path,null, ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL); }catch (InterruptedException e1) { count++; continue; } catch (KeeperException e1) { // e1.printStackTrace(); count++; continue; } // System.out.println("success to acquire lock "+id); break; } } catch (InterruptedException e) { e.printStackTrace(); } } }
2.測試線程
package com.hellojd.cloud.locks.v1; import org.apache.zookeeper.CreateMode; import org.apache.zookeeper.KeeperException; import org.apache.zookeeper.ZooDefs; import org.apache.zookeeper.data.Stat; /** * 測試線程 */ public class Task implements Runnable { private int loop; private Long lockid; ZookerSession zs; public Task(int loop,Long lockid) { zs = ZookerSession.getInstance(); this.loop = loop; this.lockid = lockid; } @Override public void run() { ZookerSession.getInstance().acquireDistributeLock(lockid); for(int i=0;i<loop;i++){ int count = getcount(); System.out.println(Thread.currentThread().getName()+"-->"+count); count(++count); } zs.releaseDistributeLock(lockid); } //計數 public void count(int count){ try { Stat s = zs.getZooKeeper().exists("/count", false); if(s==null){ System.out.println("count 不存在"); zs.getZooKeeper().create("/count",String.valueOf(count).getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); }else{ zs.getZooKeeper().setData("/count",String.valueOf(count).getBytes(),-1); } } catch (KeeperException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } } public int getcount(){ try { Stat s = zs.getZooKeeper().exists("/count", false); if(s==null){ zs.getZooKeeper().create("/count",String.valueOf(0).getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); return 0; }else{ byte[] data = zs.getZooKeeper().getData("/count", false, null); return Integer.valueOf(new String(data)); } } catch (KeeperException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } return -1; } public static void main(String[] args) { long LOCKID = 2l; for(int i=0;i<100;i++){ new Thread(new Task(1, LOCKID)).start(); } } }
原理:分布式鎖通過死循環+實現等待效果。如果線程可以創建節點,則成功獲取鎖;
釋放鎖:就是將數據節點在ZK上刪除。
缺點:簡單且性能低。有風險。如果獲取鎖的線程中斷,導致任務異常。
本文出自 “簡單” 博客,請務必保留此出處http://dba10g.blog.51cto.com/764602/1975120
最簡單分布式鎖ZK實現方案