美文网首页
分布式锁的实现几种方式

分布式锁的实现几种方式

作者: 通通小小通 | 来源:发表于2022-11-24 15:33 被阅读0次
    • 基于zookeeper原生实现分布式锁
    <dependency>
        <groupId>org.apache.zookeeper</groupId>
        <artifactId>zookeeper</artifactId>
        <version>3.8.0</version>
    </dependency>
    

    通过Watcher实现分布式锁

    @Slf4j
    public class ZkLock implements AutoCloseable, Watcher {
        private String znode;
        private ZooKeeper zooKeeper;
        public ZkLock() throws IOException {
            this.zooKeeper = new ZooKeeper("localhost:2181", 10000, this);
        }
    
        /**
         * 创建及获取锁
         */
        public boolean getLock(String businessCode) {
            try {
                // 创建业务根结点
                Stat stat = zooKeeper.exists("/" + businessCode, false);
                if (stat == null) {
                    zooKeeper.create("/" + businessCode, businessCode.getBytes(StandardCharsets.UTF_8), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
                }
                // 创建瞬时有序节点 /order/order_000001
                znode = zooKeeper.create("/" + businessCode + "/" + businessCode + "_", businessCode.getBytes(StandardCharsets.UTF_8), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT_SEQUENTIAL);
                // 获取业务节点下所有子节点
                List<String> childrenNodes = zooKeeper.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)) {
                        zooKeeper.exists("/" + businessCode + "/" + lastNode, true);
                        break;
                    }
                    lastNode = node;
                }
                // 获取不到锁,线程等待直到当前锁的删除
                synchronized (this) {
                    wait();
                }
                return true;
            } catch (Exception e) {
                e.printStackTrace();
            }
            return false;
        }
    
        @Override
        public void close() throws Exception {
            zooKeeper.delete(znode, -1);
            zooKeeper.close();
            log.info("我已经释放了锁");
        }
    
        @Override
        public void process(final WatchedEvent watchedEvent) {
            // 节点消失唤醒线程
            if (watchedEvent.getType() == Event.EventType.NodeDeleted) {
                synchronized (this) {
                    notify();
                }
            }
    
        }
    }
    

    分别开启两个服务去测试

    /**
     * 基于zookeeper原生实现分布式锁
     */
    @GetMapping("zkLock")
    public String zookeeperLock() {
       log.info("方法开始执行");
       try (ZkLock zkLock = new ZkLock()) {
           if (zkLock.getLock("order")) {
               log.info("获得了锁");
               Thread.sleep(10000);
           }
       } catch (Exception e) {
            e.printStackTrace();
       }
       log.info("方法执行完成");
       return "方法执行完成";
     }
    
    • 基本zookeeper curator客户端实现分布式锁
    <dependency>
          <groupId>org.apache.curator</groupId>
          <artifactId>curator-recipes</artifactId>
          <version>5.4.0</version>
    </dependency>
    

    配置相应的baen

    /**
     * Curator初始化连接客户端
     */
    @Bean(initMethod = "start", destroyMethod = "close")
    public CuratorFramework getCuratorFramework() {
        RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
        CuratorFramework client = CuratorFrameworkFactory.newClient("localhost:2181", retryPolicy);
        return client;
    }
    

    配置完连接后直接可以使用分布式锁了

    @Autowired
    private CuratorFramework curatorFramework;
    /**
     * 基于zookeeper curator客户端实现分布式锁(客户端已实现分布式锁)
     */
    @GetMapping("curatorLock")
    public String curatorLock() {
      log.info("方法开始执行");
      InterProcessMutex lock = new InterProcessMutex(curatorFramework, "/order");
      try {
        if (lock.acquire(30, TimeUnit.SECONDS)) {
            log.info("获得了锁");
            Thread.sleep(10000);
        }
      } catch (Exception e) {
          e.printStackTrace();
      }finally {
        try {
          log.info("释放了锁");
          lock.release();
        } catch (Exception e) {
            e.printStackTrace();
        }
      }
      log.info("方法执行完成");
      return "方法执行完成";
    }
    
    • 基础redission实现分布式锁
    <dependency>
      <groupId>org.redisson</groupId>
      <artifactId>redisson-spring-boot-starter</artifactId>
      <version>3.18.0</version>
    </dependency>
    

    yml配置

    spring:
      redis:
        host: localhost
        port: 6379
    

    配置好了之后就可以直接使用分布式锁了

    @RestController
    public class RedissonController {
        @Autowired
        private RedissonClient redissonClient;
    
        @GetMapping("redissonLock")
        public String redissonLock() {
            log.info("进入了方法");
            RLock lock = redissonClient.getLock("order");
            try {
                lock.lock(30, TimeUnit.SECONDS);
                log.info("获得了锁");
                Thread.sleep(10000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                log.info("释放🔒");
                lock.unlock();
            }
            log.info("方法请求完成");
            return "方法请求完成";
        }
    }
    

    相关文章

      网友评论

          本文标题:分布式锁的实现几种方式

          本文链接:https://www.haomeiwen.com/subject/mvpzxdtx.html