zookeeper應用之分散式鎖Java實現
原文地址:http://blog.csdn.net/z69183787/article/details/79355829
zookeeper在專案中有很多應用,其中一個比較常見的的就是分散式鎖,zookeeper實現分散式鎖的原理是根據zookeeper建立的臨時有序節點,每次zookeeper在同一個目錄下建立的臨時有序節點是有序的,會自動累加,如果本次操作建立的節點在目錄內是最小節點,則獲得鎖,否則阻塞等待鎖,並且總是在前一個節點上註冊watcher監視前一個節點的釋放,較小的節點釋放後,等待的節點對應的操作獲得鎖,以此類推,程式碼簡單實現如下:
public class ZKDisLock { private static final Logger SERVICE_LOG = LoggerFactory.getLogger(LogConstants.SERVICE_LOG); //鎖目錄 private static final String BASE_PATH = "/disLock" ; private static final String SPLIT_FLAG = "_" ; private Integer sessionOut; private String zkHost; private ZooKeeper zooKeeper; //當前鎖節點名稱 private String lockNode; //等待鎖節點名稱 private String waitNode; private CountDownLatch countDownLatch; public ZKDisLock(Integer sessionOut, String zkHost) { this .sessionOut = sessionOut; this .zkHost = zkHost; } //ZKDisLock初始化 public void init() throws DisLockException { try { zooKeeper = new ZooKeeper(zkHost, sessionOut, new Watcher() { @Override public void process(WatchedEvent watchedEvent) { } }); //判斷有無根目錄,沒有的話建立 Stat stat = zooKeeper.exists(BASE_PATH, false ); if (stat == null ) { zooKeeper.create(BASE_PATH, null , ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); } } catch (Exception e) { SERVICE_LOG.info( "zk初始化失敗" ); throw new DisLockException( "zk初始化失敗" ); } } //加鎖 public void lock(String content) throws DisLockException { if (zooKeeper == null ) { throw new DisLockException( "zk未初始化" ); } try { //建立節點 String itemName = zooKeeper.create(BASE_PATH + "/" + content + SPLIT_FLAG, null , ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL); //判斷節點是否是目錄中同一個content的最小節點 if (isLowestNode(content, itemName)) { SERVICE_LOG.info( "執行緒:" + Thread.currentThread().getId() + ",加鎖成功,節點名稱:" + lockNode); return ; } else { SERVICE_LOG.info( "執行緒:" + Thread.currentThread().getId() + ",等待鎖:" + waitNode); //不是最小節點,等待鎖釋放 waitForLock(sessionOut); //鎖釋放後,再次判斷下是否是最小節點 if (isLowestNode(content, itemName)) { SERVICE_LOG.info( "執行緒:" + Thread.currentThread().getId() + ",獲得鎖,節點名稱:" + lockNode); return ; } } } catch (Exception e) { SERVICE_LOG.error( "加鎖異常" ); throw new DisLockException( "加鎖異常" ); }
|