<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.7.0</version>
</dependency>
@Slf4j
public class ZkLock implements AutoCloseable, Watcher {
private final ZooKeeper zk;
private String znode;
public ZkLock(String zkServers) throws Exception {
zk = new ZooKeeper(zkServers, 600000, this);
}
public boolean getLock(String businessCode) {
try {
// 创建业务 根节点
Stat stat = zk.exists("/" + businessCode, false);
if (stat == null) {
zk.create("/" + businessCode, businessCode.getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
}
// 创建瞬时有序节点 /order/order_000000001
znode = zk.create("/" + businessCode + "/" + businessCode + "_", businessCode.getBytes(),
ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
// 获取所有子节点
List<String> childrenNodes = zk.getChildren("/" + businessCode, false);
// 子节点排序
Collections.sort(childrenNodes);
// 获取序号最小的(第一个)节点
String firstNode = childrenNodes.get(0);
// 判断是否是第一个节点
if (znode.endsWith(firstNode)) {
return true;
}
// 获取第一个节点的前一个节点
String lastNode = firstNode;
for (String node : childrenNodes) {
if (znode.endsWith(node)) {
zk.exists("/" + businessCode + "/" + lastNode, true);
break;
} else {
lastNode = node;
}
}
synchronized (this) {
wait();
}
return true;
} catch (KeeperException | InterruptedException e) {
e.printStackTrace();
}
return false;
}
@Override
public void close() throws Exception {
zk.delete(znode, -1);
zk.close();
log.info("zk 释放了锁");
}
@Override
public void process(WatchedEvent watchedEvent) {
if (watchedEvent.getType() == Event.EventType.NodeDeleted) {
synchronized (this) {
notify();
}
}
}
}
@Slf4j
@RestController
public class ZkLockController {
@RequestMapping("/zklock")
public String zookeeperLock() {
log.info("进入了方法");
try (ZkLock zkLock = new ZkLock("localhost:2181")){
if (zkLock.getLock("order")) {
log.info("获取锁成功");
Thread.sleep(5000);
}
} catch (Exception e) {
e.printStackTrace();
}
log.info("结束了方法");
return "结束了方法";
}
}