Zookeeper實現分佈式鎖
- 原生API實現
1.每個客戶端往/Locks下創建臨時有序節點/Locks/Lock 000000001
2.客戶端取得/Locks下子節點,並進行排序,判斷排在最前面的是否爲自己,如果自己的鎖節點在第一位代表獲取鎖成功
3.如果自己的鎖節點不在第一位,則監聽自己前一位的鎖節點。例如,自己鎖節點 Lock 000000001
4.當前一位鎖節點(Lock 000000002)的邏輯
5.監聽客戶端重新執行第2步邏輯,判斷自己是否獲得了鎖
/**
* @Author: zxx
* @Date: 2020/3/30 21:43
* @Description: 生成唯一ID
*/
public class ZKUniqueID implements Watcher{
// 計數器對象
public static CountDownLatch countDownLatch=new CountDownLatch(1);
// 連接對象
public static ZooKeeper zooKeeper;
private String IP = "192.168.21.141:2181";
// 用戶生成序號的節點
String defaultPath = "/uniqueId";
public ZKUniqueID() throws Exception {
zooKeeper = new ZooKeeper(IP, 6000, this);
countDownLatch.await();
}
public void process(WatchedEvent watchedEvent) {
try {
//EventType = None時
if (watchedEvent.getType() == Watcher.Event.EventType.None){
if (watchedEvent.getState() == Watcher.Event.KeeperState.SyncConnected){
System.out.println("連接成功");
countDownLatch.countDown();
}else if (watchedEvent.getState() == Watcher.Event.KeeperState.Disconnected){
System.out.println("斷開連接");
}else if (watchedEvent.getState() == Watcher.Event.KeeperState.Expired){
System.out.println("會話超時");
}else if (watchedEvent.getState() == Watcher.Event.KeeperState.AuthFailed){
System.out.println("認證失敗");
}
}
}catch (Exception e){
e.printStackTrace();
}
}
public String getUniqueID() {
String path ="";
//創建臨時有序節點
try {
path = zooKeeper.create(defaultPath,new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
} catch (KeeperException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
return path.substring(8);
}
@Test
public void test() throws Exception {
ZKUniqueID zkUniqueID = new ZKUniqueID();
for(int i=0 ;i<3;i++){
System.out.println(zkUniqueID.getUniqueID());
}
}
}
-
curator實現
-
InterProcessMutex: 分佈式可重入排他鎖
-
InterProcessReadWriteLock:分佈式讀寫鎖
@Test
public void lock1() throws Exception {
// 排他鎖
// arg1:連接對象
// arg2:節點路徑
InterProcessLock interProcessLock = new InterProcessMutex(client, "/lock1");
System.out.println("等待獲取鎖對象!");
// 獲取鎖
interProcessLock.acquire();
for (int i = 1; i <= 10; i++) {
Thread.sleep(3000);
System.out.println(i);
}
// 釋放鎖
interProcessLock.release();
System.out.println("等待釋放鎖!");
}
//讀鎖
@Test
public void lock2() throws Exception {
// 讀寫鎖
InterProcessReadWriteLock interProcessReadWriteLock=new InterProcessReadWriteLock(client, "/lock1");
// 獲取讀鎖對象
InterProcessLock interProcessLock=interProcessReadWriteLock.readLock();
System.out.println("等待獲取鎖對象!");
// 獲取鎖
interProcessLock.acquire();
for (int i = 1; i <= 10; i++) {
Thread.sleep(3000);
System.out.println(i);
}
// 釋放鎖
interProcessLock.release();
System.out.println("等待釋放鎖!");
}
//寫鎖
@Test
public void lock3() throws Exception {
// 讀寫鎖
InterProcessReadWriteLock interProcessReadWriteLock=new InterProcessReadWriteLock(client, "/lock1");
// 獲取寫鎖對象
InterProcessLock interProcessLock=interProcessReadWriteLock.writeLock();
System.out.println("等待獲取鎖對象!");
// 獲取鎖
interProcessLock.acquire();
for (int i = 1; i <= 10; i++) {
Thread.sleep(3000);
System.out.println(i);
}
// 釋放鎖
interProcessLock.release();
System.out.println("等待釋放鎖!");
}