2023-01-12
節點
4.1. 父類的設計
設計父類,提供連接ZooKeeper服務端的邏輯、節點操作的邏輯,所有方式實現的鎖都需要繼承自這個類。
package com.qianfeng.lock;
import org.apache.zookeeper.*;
import org.apache.zookeeper.data.Stat;
import java.io.IOException;
import java.util.concurrent.CountDownLatch;
/**
* @author 千鋒大數據教研院 - 章魚哥
* @company 北京千鋒互聯科技有限公司
*/
public abstract class ZkLockerBase implements Watcher {
/**
* 操作的鎖名稱
*/
protected String lockName;
/**
* ZooKeeper連接客戶端
*/
private ZooKeeper zkCli = null;
/**
* 確保可以連接到ZooKeeper客戶端
*/
private final CountDownLatch latch = new CountDownLatch(1);
/**
* 鎖的根節點名稱
*/
protected String rootNodeName = "/zk-lock";
/**
* 連接到預設的服務器
*/
public ZkLockerBase() {
this("qianfeng01:2181,qianfeng02:2181,qianfeng03:2181");
}
/**
* 連接到ZooKeeper的指定服務端
* @param connectString 連接字符串
*/
public ZkLockerBase(String connectString) {
try {
// 連接到ZooKeeper服務端
this.zkCli = new ZooKeeper(connectString, 5000, this);
// 等待連接成功的信號
this.latch.await();
// 創建根節點
createRootNode();
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
}
public ZkLockerBase(String connectString, String lockName) {
this(connectString);
this.lockName = lockName;
}
/**
* 創建節點
* @param nodeName 創建的節點名稱
* @param createMode 創建模式
* @return 創建成功的節點名稱,如果創建失敗,返回null
*/
public String createNode(String nodeName, CreateMode createMode) {
try {
// 創建節點,并返回創建成功之后的節點名稱
return this.zkCli.create(nodeName, "".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, createMode);
} catch (KeeperException | InterruptedException ignored) {
}
return null;
}
/**
* 刪除節點
* @param nodeName 刪除的節點名稱
* @return 刪除的結果
*/
public boolean deleteNode(String nodeName) {
try {
// 刪除節點
this.zkCli.delete(nodeName, -1);
return true;
} catch (InterruptedException | KeeperException ignored) {
}
return false;
}
/**
* 判斷節點是否存在
* @param nodeName 節點的名字
* @return 是否存在
*/
public boolean exists(String nodeName) {
try {
Stat exists = zkCli.exists(nodeName, false);
return exists != null;
} catch (KeeperException | InterruptedException e) {
e.printStackTrace();
}
return false;
}
/**
* 創建根節點,存放所有的節點或者子節點實現的鎖
*/
public void createRootNode() {
if (!exists(this.rootNodeName)) {
createNode(this.rootNodeName, CreateMode.CONTAINER);
}
}
public String getLockName() {
return this.rootNodeName + "/" + lockName;
}
public ZooKeeper getZkCli() {
return zkCli;
}
@Override
public void process(WatchedEvent event) {
switch (event.getType()) {
case None:
if (event.getState().equals(Event.KeeperState.SyncConnected)) {
// 說明連接到服務端成功
this.latch.countDown();
}
case NodeCreated:
processCreatedNode(event);
break;
case NodeDeleted:
processDeleteNode(event);
break;
case NodeChildrenChanged:
processChildernChange(event);
break;
}
}
// 創建節點回調
protected void processCreatedNode(WatchedEvent event) {}
// 刪除節點回調
protected void processDeleteNode(WatchedEvent event) {}
// 子節點變更回調
protected void processChildernChange(WatchedEvent event) {}
}
鎖接口的設計
提供所有的鎖必須要實現的功能,制定鎖的規范。
package com.qianfeng.lock;
/**
* ZooKeeper分布式鎖通用接口
*
* @author 千鋒大數據教研院 - 章魚哥
* @company 北京千鋒互聯科技有限公司
*/
public interface ZkLocker {
/**
* 上鎖
*/
boolean lock();
/**
* 解鎖
*/
boolean unlock();
/**
* 判斷鎖是否存在
* @return 是否存在
*/
boolean exists();
}
4.3. 節點實現的非阻塞性鎖
package com.qianfeng.lock.nodeLock;
import com.qianfeng.lock.ZkLocker;
import com.qianfeng.lock.ZkLockerBase;
import org.apache.zookeeper.CreateMode;
/**
* @author 千鋒大數據教研院 - 章魚哥
* @company 北京千鋒互聯科技有限公司
*/
public class ZkLockerNodeNoneBlockingLocker extends ZkLockerBase implements ZkLocker {
public ZkLockerNodeNoneBlockingLocker(String connectString, String lockName) {
super(connectString, lockName);
}
public ZkLockerNodeNoneBlockingLocker(String lockName) {
super();
this.lockName = lockName;
}
/**
* 上鎖
*/
@Override
public boolean lock() {
// 1. 拼接完整的節點路徑
String lockNode = this.rootNodeName + "/" + lockName;
// 2. 創建鎖
return createNode(lockNode, CreateMode.EPHEMERAL) != null;
}
/**
* 解鎖
*/
@Override
public boolean unlock() {
// 1. 拼接完整的節點路徑
String lockNode = this.rootNodeName + "/" + lockName;
// 2. 刪除鎖
return deleteNode(lockNode);
}
/**
* 判斷鎖是否存在
*
* @return 是否存在
*/
@Override
public boolean exists() {
// 1. 拼接完整的節點路徑
String lockNode = this.rootNodeName + "/" + lockName;
// 2. 判斷是否存在
return super.exists(lockNode);
}
}
開班時間:2021-04-12(深圳)
開班盛況開班時間:2021-05-17(北京)
開班盛況開班時間:2021-03-22(杭州)
開班盛況開班時間:2021-04-26(北京)
開班盛況開班時間:2021-05-10(北京)
開班盛況開班時間:2021-02-22(北京)
開班盛況開班時間:2021-07-12(北京)
預約報名開班時間:2020-09-21(上海)
開班盛況開班時間:2021-07-12(北京)
預約報名開班時間:2019-07-22(北京)
開班盛況Copyright 2011-2023 北京千鋒互聯科技有限公司 .All Right 京ICP備12003911號-5 京公網安備 11010802035720號