基於ZK的分布式鎖實現


import java.util.concurrent.TimeUnit;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.recipes.locks.InterProcessMutex;
import org.apache.curator.retry.RetryNTimes;

/**
 * ZooKeeper節點類型: <br>
 * ZooKeeper 節點是有生命周期的,這取決於節點的類型。<br>
 * 在 ZooKeeper 中,節點類型可以分為持久節點(PERSISTENT)、臨時節點(EPHEMERAL),以及時序節點(SEQUENTIAL)<br>
 * 具體在節點創建過程中,一般是組合使用,可以生成以下 4種節點類型<br>
 * 
 * 持久節點(PERSISTENT) <br>
 * 所謂持久節點,是指在節點創建后,就一直存在,直到有刪除操作來主動清除這個節點。 <br>
 * (該節點不會因為創建該節點的客戶端會話失效而消失)
 * 
 * 臨時節點(EPHEMERAL) <br>
 * 和持久節點不同的是,臨時節點的生命周期和客戶端會話綁定。<br>
 * 如果客戶端會話失效,那么這個節點就會自動被清除掉。<br>
 * (這里提到的是會話失效,而非連接斷開)<br>
 * 另外,在臨時節點下面不能創建子節點。<br>
 * 
 * 持久順序節點(PERSISTENT_SEQUENTIAL) <br>
 * 這類節點的基本特性和上面的持久節點類型是一致的。<br>
 * 額外的特性是,在ZK中,每個父節點會為他的第一級子節點維護一份時序,會記錄每個子節點創建的先后順序。 <br>
 * 基於這個特性,在創建子節點的時候,可以設置這個屬性,那么在創建節點過程中,ZK會自動為給定節點名加上一個數字后綴,作為新的節點名。這個數字后綴的范圍是整型的最大值。<br>
 * 假如: 我們在/lock/目錄下創建節3個點,集群會按照提起創建的順序來創建節點,節點分別為/lock/0000000001、/lock/0000000002、/lock/0000000003。
 * 
 * 臨時順序節點(EPHEMERAL_SEQUENTIAL) <br>
 * 具有臨時節點和順序節點的特性。我們可以利用這個特性來實現分布式鎖。 <br>
 * 基於zookeeper瞬時有序節點實現的分布式鎖,其主要邏輯如下: <br>
 * 客戶端對某個功能加鎖時,在zookeeper上的與該功能對應的指定節點的目錄下,生成一個唯一的瞬時有序節點。 <br>
 * 判斷是否獲取鎖的方式,只需要判斷有序節點中序號最小的一個,如果最小的節點與當客戶端記錄節點號相同獲得鎖<br>
 * 當釋放鎖的時候,只需將這個瞬時節點刪除即可。 <br>
 * 
 * Curator是Netflix公司開源的一個Zookeeper客戶端,提供了一些操作Zookeeper的方法,其中包括創建分布式鎖 <br>
 *
 * @author _yyl */ public class CuratorDistributedLockTest { private static final String ZK_ADDRESS = "localhost:2181"; private static final String ZK_LOCK_PATH = "/zktest/lock0"; /** * 下面的程序會啟動幾個線程去爭奪鎖,拿到鎖的線程會占用5秒 */ public static void main(String[] args) throws InterruptedException { // 1.Connect to zk CuratorFramework client = CuratorFrameworkFactory.newClient(ZK_ADDRESS, new RetryNTimes(10, 5000)); client.start(); System.out.println(client.getState()); System.out.println("zk client start successfully!"); InterProcessMutex lock = new InterProcessMutex(client, ZK_LOCK_PATH); for (int i = 0; i < 3; i++) { new Thread(() -> { doWithLock(client, lock); }, "Thread-" + i).start(); } } private static void doWithLock(CuratorFramework client, InterProcessMutex lock) { try { String name = Thread.currentThread().getName(); if (lock.acquire(10 * 1000, TimeUnit.SECONDS)) { System.out.println(name + " hold lock"); System.out.println(client.getChildren().forPath(ZK_LOCK_PATH)); Thread.sleep(5000L); System.out.println(name + " release lock"); } } catch (Exception e) { e.printStackTrace(); } finally { try { lock.release(); } catch (Exception e) { e.printStackTrace(); } } } }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM