基于zk“临时顺序节点“的分布式锁
Posted zzq-include
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基于zk“临时顺序节点“的分布式锁相关的知识,希望对你有一定的参考价值。
import org.apache.zookeeper.*; import org.apache.zookeeper.data.Stat; import java.io.IOException; import java.util.List; import java.util.concurrent.CountDownLatch; /** * Created by zzq on 2019/6/25. */ public class ZKLock implements Watcher private ZooKeeper zk; //当前锁 private String currentLock; //资源名称 private String lockName; //锁根节点 private String ROOT_LOCK = "/root_lock"; //锁的各个资源根节点 private String tmpRootLock; //由于zookeeper监听节点状态会立即返回,所以需要使用CountDownLatch(也可使用信号量等其他机制) private CountDownLatch latch; public ZKLock(String zkAddress, String lockName) this.lockName = "" + System.nanoTime(); try zk = new ZooKeeper(zkAddress, 30000, this); createZNode(ROOT_LOCK, CreateMode.PERSISTENT); tmpRootLock = ROOT_LOCK + "/" + lockName; createZNode(tmpRootLock, CreateMode.PERSISTENT);//****zk临时节点下不能创建临时顺序节点 catch (IOException e) e.printStackTrace(); catch (KeeperException e) e.printStackTrace(); catch (InterruptedException e) e.printStackTrace(); private void createZNode(String node, CreateMode mode) throws KeeperException, InterruptedException //获取根节点状态 Stat stat = zk.exists(node, false); //如果根节点不存在,则创建根节点,根节点类型为永久节点 if (stat == null) zk.create(node, new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, mode); public void lock() try //在根节点下创建临时顺序节点,返回值为创建的节点路径 currentLock = zk.create(tmpRootLock + "/" + lockName, new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL); //获取根节点下的所有临时顺序节点,不设置监视器 List<String> children = zk.getChildren(tmpRootLock, false); //对根节点下的所有临时顺序节点进行从小到大排序 children.sort(null); //判断当前节点是否为最小节点,如果是则获取锁,若不是,则找到自己的前一个节点,监听其存在状态 int curIndex = children.indexOf(currentLock.substring(currentLock.lastIndexOf("/") + 1)); if (curIndex != 0) //获取当前节点前一个节点的路径 String prev = children.get(curIndex - 1); //监听当前节点的前一个节点的状态,null则节点不存在 Stat stat = zk.exists(tmpRootLock + "/" + prev, true); //此处再次判断该节点是否存在 if (stat != null) latch = new CountDownLatch(1); //进入等待锁状态 latch.await(); latch = null; catch (KeeperException e) e.printStackTrace(); catch (InterruptedException e) e.printStackTrace(); //释放锁 public void unlock() try //删除创建的节点 zk.delete(currentLock, -1); List<String> children = zk.getChildren(tmpRootLock, false); if (children.size() == 0) zk.delete(tmpRootLock, -1); //关闭zookeeper连接 zk.close(); catch (InterruptedException e) e.printStackTrace(); catch (KeeperException e) e.printStackTrace(); currentLock = null; @Override public void process(WatchedEvent event) if (this.latch != null) latch.countDown(); public static void main(String[] args) throws Exception for (int i = 0; i < 7; i++) // new Thread(new Runnable() // @Override // public void run() // ZKLock lock = new ZKLock("10.10.210.123:2181", "lock"); // SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); // lock.lock(); // // ).start(); ZKLock lock = new ZKLock("10.10.210.123:2181", "L1"); lock.lock(); ZKLock lock1 = new ZKLock("10.10.210.123:2181", "L2"); lock1.lock(); lock1.unlock(); lock.unlock(); String uu = "";
以上是关于基于zk“临时顺序节点“的分布式锁的主要内容,如果未能解决你的问题,请参考以下文章
spring boot 定时任务基于zookeeper的分布式锁实现