分布式锁-基于Zookeeper实现
1. Zookeeper安装部署 1.1 安装部署参考文档 分布式注册中心-Zookeeper: https://github.com/FocusProgram/person-improve/tree/main/springcloud-zookeeper
1.2 Zookeeper客户端工具 下载地址:https://issues.apache.org/jira/secure/attachment/12436620/ZooInspector.zip
2. 实现原理
多个JVM同时在根节点下创建临时节点(/lock)
创建临时节点(/lock)成功,则获取锁成功,执行响应的逻辑代码
创建临时节点(/lock)失败,则获取锁失败,通过订阅节点删除通知事件,如果节点删除则重新获取锁,否则就一直等待
执行响应业务逻辑完成后关闭连接,临时节点删除,锁释放
3. 具体实现 3.1 引入Gradle依赖 1 2 3 dependencies { compile group : 'com.101tec' , name: 'zkclient' , version: '0.11' }
3.2 具体业务实现 3.2.1 创建CustomLock接口 1 2 3 4 5 6 7 8 9 10 11 12 public interface CustomLock { public void getLock () ; public void unLock () ; }
3.2.2 创建ZookeeperAbstractLock抽象类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 public abstract class ZookeeperAbstractLock implements CustomLock { private String CONNECTSTRING = "114.55.34.44:2181" ; protected ZkClient zkClient = new ZkClient(CONNECTSTRING); protected String PATH = "/lock" ; protected CountDownLatch countDownLatch = new CountDownLatch(1 ); @Override public void getLock () { if (tryLock()) { System.out .println("获取lock锁的资源" ); } else { waitLock(); getLock(); } } @Override public void unLock () { if (zkClient != null ) { zkClient.close(); System.out .println("释放lock锁资源" ); } } protected abstract void waitLock () ; protected abstract boolean tryLock () ; }
3.2.3 创建ZookeeperDistrbuteLock抽象类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 public class ZookeeperDistrbuteLock extends ZookeeperAbstractLock { @Override protected void waitLock () { IZkDataListener iZkDataListener = new IZkDataListener () { @Override public void handleDataChange (String dataPath, Object data) throws Exception { } @Override public void handleDataDeleted (String dataPath) throws Exception { System.out.println("删除的节点路径为" + dataPath); if (countDownLatch != null ) { countDownLatch.countDown(); } } }; zkClient.subscribeDataChanges(PATH, iZkDataListener); if (zkClient.exists(PATH)) { countDownLatch = new CountDownLatch (1 ); try { countDownLatch.await(); } catch (Exception e) { e.printStackTrace(); } } zkClient.unsubscribeDataChanges(PATH, iZkDataListener); } @Override protected boolean tryLock () { try { zkClient.createEphemeral(PATH); System.out.println("获取lock锁成功" ); return true ; } catch (Exception e) { System.out.println("获取lock锁失败" ); return false ; } } }
3.2.4 使用Zookeeper实现分布式锁 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 public class NumberGenerator { private static int count = 0 ; public String getNumber() { SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss" ); return simpleDateFormat.format(new Date()) + "-" + ++count ; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 public class OrderService implements Runnable { private NumberGenerator numberGenerator = new NumberGenerator (); private CustomLock customLock = new ZookeeperDistrbuteLock (); @Override public void run ( ) { getNumber (); } public void getNumber ( ) { try { customLock.getLock (); String number = numberGenerator.getNumber (); System .out .println (Thread .currentThread ().getName () + "生成订单号:" + number ); } catch (Exception e) { e.printStackTrace (); } finally { customLock.unLock (); } } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 public class LockTest { private static final int CPU_COUNT = Runtime.getRuntime ().availableProcessors (); private static final int CORE_POOL_SIZE = CPU_COUNT + 1 ; private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1 ; private static final int KEEP_ALIVE = 1 ; public static void main (String [] args) { System.out.println ("开始生成订单号......" ); long begin = System.currentTimeMillis (); for (int i = 0 ; i < 10 ; i++) { new Thread (new OrderService ()).start (); } long end = System.currentTimeMillis (); long result = end - begin; System.out.println ("执行消耗时长:" + result / 1000 + "s" ); } }
3.2.5 源码参考地址 https://github.com/FocusProgram/person-improve/tree/main/springcloud-zookeeper-lock