zookeeperAPI
package zkApI;
import org.apache.zookeeper.*;
import org.apache.zookeeper.data.Stat;
import org.junit.Before;
import org.junit.Test;
import java.io.IOException;
import java.util.List;
/**
* @Author: Braylon
* @Date: 2020/1/30 10:47
* @Version: 1.0
*/
public class zookeeper {
//對集羣的配置,這裏使用僞分佈
private static String destination = "ip:2181";
private static int sessionTimeout = 2000;
private ZooKeeper zkClient = null;
@Before
public void init() throws IOException {
zkClient = new ZooKeeper(destination, sessionTimeout, new Watcher() {
@Override
public void process(WatchedEvent watchedEvent) {
//收到事件通知後執行的函數,也就似乎用戶的業務邏輯
System.out.println("監聽" + "\001" + watchedEvent.getPath());
//重新開始監聽
try {
zkClient.getChildren("/", true);
} catch (KeeperException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
@Test
public void crearePoint() {
/*對於create方法
* P1:創建的節點路徑
* P2:數據
* P3:節點的權限
* P4:節點的類型
* */
try {
zkClient.create("/braylon", "point01".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
} catch (KeeperException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Test
public void getChild() {
try {
List<String> children = zkClient.getChildren("/", true);
for (String c : children) {
System.out.println(c);
}
//延時阻塞
Thread.sleep(Long.MAX_VALUE);
} catch (KeeperException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Test
public void isExited() {
try {
Stat s = zkClient.exists("/braylon", false);
System.out.println(s == null ? "不存在" : "存在");
} catch (KeeperException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
這裏其實沒有什麼特別好說的,因爲基本上都是很簡單的操作,不過可以可以關注一下,@Before這個並不是zookeeper開發包中的,而是junit中的,答題的邏輯就是在運行Test之前先運行@Before註解下的監聽器。
大家運行一些就明白了。
分佈式鎖
分佈式鎖一共有三種無非是利用原子性操作來達到。
- 數據庫
- redis
- zookeeper鎖
都可以實現分佈式鎖,
我知道的是redis用的好像比較多,當然我在上本科,所以也許是沒有接觸過特別高逼格的分佈式鎖。但是我一直覺得zookeeper鎖使用比redis更加簡單,主要應該是本身zookeeper的機制和開發包的封裝性已經非常“傻瓜了”。
這裏我分享一個小demo:
我使用的就是一個本地部署zookeeper的虛擬機,哈哈很簡單吧。
package zkApI;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.recipes.locks.InterProcessLock;
import org.apache.curator.framework.recipes.locks.InterProcessMutex;
import org.apache.curator.retry.ExponentialBackoffRetry;
/**
* @Author: Braylon
* @Date: 2020/1/30 11:23
* @Version: 1.0
*/
public class zkDistributionLock {
private static Integer sharedResource = 5;
public static void print() {
System.out.println("**************" + Thread.currentThread().getName() + "**************");
System.out.println("Get sharedResource");
if (sharedResource == 0) {
System.out.println("sorry, your operation fails");
return;
}
sharedResource = sharedResource - 1;
System.out.println("left " + sharedResource);
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("************************done\n");
}
public static void main(String[] args) {
//等待時間和最大重試次數
ExponentialBackoffRetry policy = new ExponentialBackoffRetry(1000, 10);
CuratorFramework client = CuratorFrameworkFactory.builder().connectString("ip:2181").retryPolicy(policy).build();
//生成鎖
client.start();
final InterProcessMutex mutex = new InterProcessMutex(client, "/lock0130");
//多線程併發訪問
for (int i = 0; i < 10; i++) {
new Thread(new Runnable() {
@Override
public void run() {
try {
//在訪問共享資源之前獲得鎖
mutex.acquire();
print();
} catch (Exception e) {
e.printStackTrace();
}finally {
//釋放鎖
try {
mutex.release();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}).start();
}
}
}
歡迎大神指點
祝福武漢
大家共勉~~