API
依赖
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>RELEASE</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.8.2</version>
</dependency>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.5.9</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>4.3.0</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>4.3.0</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-client</artifactId>
<version>4.3.0</version>
</dependency>
方法
zkClient = new ZooKeeper(connectString, sessionTimeout, new Watcher() {
@Override
public void process(WatchedEvent watchedEvent) {
try {
if (watchedEvent.getType() == Event.EventType.NodeChildrenChanged) {
List<String> children = zkClient.getChildren("/", true);
System.out.println(children);
} else {
System.out.println(watchedEvent);
}
} catch (Exception e) {
e.printStackTrace();
}
}
});
String res = zkClient.create("/api", "test.api".getBytes(StandardCharsets.UTF_8),
ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT)
- 获取子节点,并且监听为true,就是用创建时的监听方法
List<String> children = zkClient.getChildren("/", true)
- 判断某一个节点是否存在,不存在返回null,存在返回节点信息
Stat exists = zkClient.exists("/api", false)
Stat exists = zkClient.exists("/api", false)
byte[] data = zkClient.getData("/api", false, exists)
System.out.println(exists)
System.out.println(new String(data))
Stat stat = zkClient.setData("/api", "hello".getBytes(StandardCharsets.UTF_8), exists.getVersion())
data = zkClient.getData("/api", false, stat)
System.out.println(stat)
System.out.println(new String(data))
动态上下线
public class DistributeServer {
private String connectString = "localhost:2181";
private int sessionTimeout = 2000;
private ZooKeeper zooKeeper;
public static void main(String[] args) throws Exception {
DistributeServer server = new DistributeServer();
server.getConnect();
server.regist(args[0]);
Thread.sleep(100000);
}
private void regist(String host) throws Exception {
String s = zooKeeper.create("/servers/" + host, host.getBytes(StandardCharsets.UTF_8),
ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
System.out.println(host + " 已经上线...");
}
private void getConnect() throws IOException {
zooKeeper = new ZooKeeper(connectString, sessionTimeout, new Watcher() {
@Override
public void process(WatchedEvent watchedEvent) {
}
});
}
}
public class DistributeClient {
private ZooKeeper zooKeeper;
private String connectString = "localhost:2181";
private int sessionTimeout = 2000;
public static void main(String[] args) throws Exception {
DistributeClient client = new DistributeClient();
client.getConnect();
client.getServerList();
Thread.sleep(1000000);
}
private void getServerList() throws Exception {
List<String> children = zooKeeper.getChildren("/servers", true);
List<String> servers = new ArrayList<>();
for (String child : children) {
byte[] data = zooKeeper.getData("/servers/" + child, false, null);
servers.add(new String(data));
}
System.out.println(servers);
}
private void getConnect() throws Exception {
zooKeeper = new ZooKeeper(connectString, sessionTimeout, new Watcher() {
@Override
public void process(WatchedEvent watchedEvent) {
if (watchedEvent.getType() == Event.EventType.NodeChildrenChanged) {
try {
getServerList();
} catch (Exception e) {
e.printStackTrace();
}
} else {
System.out.println(watchedEvent);
}
}
});
}
}
分布式锁
API实现
- 收到请求后,在
/locks
创建一个临时顺序节点,序号最小的节点,有操作权
- 其他业务监听
locks
的子节点变化,判断自己是否是最小的节点
- 执行完业务后,删除节点,下面的节点收到通知,进行业务操作
- 测试类
public class DistributeLockTest {
public static void main(String[] args) throws Exception {
DistributeLock lock1 = new DistributeLock();
DistributeLock lock2 = new DistributeLock();
new Thread(new Runnable() {
@Override
public void run() {
try {
lock1.zkLock();
System.out.println(Thread.currentThread() + " 启动...");
Thread.sleep(10000);
lock1.unZkLock();
System.out.println(Thread.currentThread() + " 结束...");
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
try {
lock2.zkLock();
System.out.println(Thread.currentThread() + " 启动...");
Thread.sleep(10000);
lock2.unZkLock();
System.out.println(Thread.currentThread() + " 结束...");
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
}
public class DistributeLock {
private final String connectString = "localhost:2181";
private final int sessionTimeout = 2000;
private final ZooKeeper zooKeeper;
private String lastPath;
private CountDownLatch countDownLatch = new CountDownLatch(1);
private CountDownLatch waitLatch = new CountDownLatch(1);
private String currentNode;
public DistributeLock() throws Exception {
zooKeeper = new ZooKeeper(connectString, sessionTimeout, new Watcher() {
@Override
public void process(WatchedEvent watchedEvent) {
if (watchedEvent.getType() == Event.EventType.NodeDeleted &&
watchedEvent.getPath().equals(lastPath)) {
System.out.println("watchedEvent: " + watchedEvent);
waitLatch.countDown();
}
if (watchedEvent.getState() == Event.KeeperState.SyncConnected) {
countDownLatch.countDown();
}
}
});
countDownLatch.await();
Stat stat = zooKeeper.exists("/locks", false);
if (stat != null) {
return;
}
zooKeeper.create("/locks", "locks".getBytes(StandardCharsets.UTF_8),
ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
}
public void zkLock() throws Exception{
currentNode = zooKeeper.create("/locks/" + "lock-", null,
ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
List<String> children = zooKeeper.getChildren("/locks", false);
if (children.size() == 1) {
return;
} else {
Collections.sort(children);
String sub = currentNode.substring("/locks/".length());
int idx = children.indexOf(sub);
if (idx == -1) {
System.out.println("数据异常");
} else if (idx == 0) {
return;
} else {
lastPath = "/locks/" + children.get(idx - 1);
zooKeeper.getData(lastPath, true, null);
waitLatch.await();
return;
}
}
}
public void unZkLock() throws Exception{
zooKeeper.delete(currentNode, -1);
}
}
Curator框架
public class CuratorLockTest {
public static void main(String[] args) {
InterProcessMutex lock1 = new InterProcessMutex(getCuratorFramework(), "/locks");
InterProcessMutex lock2 = new InterProcessMutex(getCuratorFramework(), "/locks");
new Thread(new Runnable() {
@Override
public void run() {
try {
lock1.acquire();
System.out.println(Thread.currentThread() + " 获取到锁...");
lock1.acquire();
Thread.sleep(5000);
lock1.release();
lock1.release();
System.out.println(Thread.currentThread() + " 释放锁...");
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
try {
lock2.acquire();
System.out.println(Thread.currentThread() + " 获取到锁...");
lock2.acquire();
Thread.sleep(5000);
lock2.release();
lock2.release();
System.out.println(Thread.currentThread() + " 释放锁...");
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
private static CuratorFramework getCuratorFramework() {
ExponentialBackoffRetry policy = new ExponentialBackoffRetry(3000, 3);
CuratorFramework client = CuratorFrameworkFactory.builder().connectString("localhost:2181")
.connectionTimeoutMs(2000)
.sessionTimeoutMs(2000)
.retryPolicy(policy).build();
client.start();
System.out.println("zookeeper 启动...");
return client;
}
}