1.临时节点方式的ZK分布式锁,这种方实现方式适用于zkClient较少的场景,当zkClient很多时会出现羊群效应(节点变动时zkServer端需要通知每个zkClient, 此时zkServer消耗较大)
publicclass ZkLock{
private ZooKeeper zkClient;
public ZkLock() {
try {
zkClient = new ZooKeeper("127.0.0.1:2181",30000,
new Watcher() {
publicvoid process(WatchedEvent event) {
System.out.println("xxx");
}
});
}catch (IOException e) {
e.printStackTrace();
}
}
publicvoid lock() {
try {
while(!this.tryLock()) {
CountDownLatchcdl = new CountDownLatch(1);
zkClient.exists("/lock", new Watcher() {
publicvoid process(WatchedEvent event) {
cdl.countDown();
}
});
cdl.await();
}
}catch (Exception e) {
e.printStackTrace();
}
}
privateboolean tryLock() {
booleanlock = true;
try {
zkClient.create("/lock", "lock".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
}catch (KeeperException e) {
lock = false;
e.printStackTrace();
}catch (InterruptedException e) {
e.printStackTrace();
}
returnlock;
}
publicvoid unlock() {
try {
zkClient.delete("/lock", 0);
}
catch (Exception e) {
e.printStackTrace();
}
}
}
2.临时顺序节点方式的ZK分布式锁,这种方实现方式相对顺序节点方式,当节点变化时zkServer不用通知的每一个zkClient(zkClient监听的是子节点,不同的zkClient会监听不通的子节点,一定程度上避免了羊群效应)
publicclass ZkLock{
private ZooKeeper zkClient;
private String rootNode = "/lock";
private String currentLockNodePath;
public ZkLock() {
try {
zkClient = new ZooKeeper("127.0.0.1:2181",30000,
new Watcher() {
publicvoid process(WatchedEvent event) {
System.out.println("xxx");
}
});
}catch (IOException e) {
e.printStackTrace();
}
}
publicvoid lock() {
try {
String currentLockNodePath = zkClient.create(
rootNode + "/", "lock".getBytes(),
Ids.OPEN_ACL_UNSAFE,
CreateMode.EPHEMERAL_SEQUENTIAL);
List<String> children =
zkClient.getChildren(rootNode, false);
children.sort(null);
String[] temps = currentLockNodePath.split("/");
String currentLockNode = temps[temps.length - 1];
//判断当前节点是否为最小节点,如果是则获取锁,若不是,
//则找到自己的前一个节点,监听其存在状态
intcurIndex = children.indexOf(currentLockNode);
if(curIndex == 0) {
this.currentLockNodePath = currentLockNodePath;
}
else {
Stringprev = children.get(curIndex - 1);
CountDownLatchcdl = new CountDownLatch(1);
zkClient.exists(rootNode + "/" + prev,
new Watcher() {
publicvoid process(WatchedEvent event) {
cdl.countDown();
}
});
cdl.await();
}
}catch (Exception e) {
e.printStackTrace();
}
}
publicvoid unlock() {
try {
zkClient.delete(currentLockNodePath, 0);
}
catch (Exception e) {
e.printStackTrace();
}
}
}




