• 售前

  • 售后

热门帖子
入门百科

通过SpringBoot更优雅的实现分布式锁(Spring Integration)

[复制链接]
李墨285 显示全部楼层 发表于 2022-1-8 18:15:15 |阅读模式 打印 上一主题 下一主题
一、概述

之前的文章中,有提到过用redission组件实现分布式锁,现实上除了几种经常被采用的,如:


  • 基于关系型数据库
  • 基于Redission组件
  • 基于Apache Curator组件,通过Zk的临时顺序节点模子实现的
除了以上比力常用的方式,这篇文章简单说一下感觉被大伙儿忽略的一种实现方式,那就是通过 Spring Integration 这个新兴组件来实现,现实上它的焦点目标就是提供一个简单的模子来实现复杂的企业集成解决方案,为基于Spring的应用添加异步的、消息驱动的举动,让Spring用户可以直观的、增量的采用,更详细的内容可以通过官网深入相识。Spring Integration提供的全局锁现在为如下存储提供了实现:


  • Redis
  • Zookeeper
  • Gemfire
  • JDBC
它们利用类似的API抽象,这意味着,不论利用哪种存储,你的编码体验都是一样的。试想一下你当前项目是基于zookeeper实现的分布式锁,后续由于特殊需求厘革,你想换成redis的实现,我们只需要修改相干依赖和设置就可以了,无需修改代码。
二、API阐明

在利用 Spring Integration 实现分布式锁之前,我们需要重点关注几个方法:
lock():加锁,如果已经被其他线程锁住或者当火线程不能获取锁则壅闭;
lockInterruptibly():加锁,除非当火线程被打断;
tryLock():尝试加锁,如果已经有其他锁锁住,获取当火线程不能加锁,则返回false,加锁失败;加锁成功则返回true;
tryLock(long time, TimeUnit unit):尝试在指定时间内加锁,如果已经有其他锁锁住,获取当火线程不能加锁,则返回false,加锁失败;加锁成功则返回true;
unlock():R解锁。
三、案例

采用Redis和Zookeeper可能各人更密切,就以这俩为例,JDBC和Gemfire可以本身玩玩,Gemfire实在我也不会,嗯:


  • 依赖
  1. <dependencies>
  2.     <dependency>
  3.         <groupId>org.springframework.boot</groupId>
  4.         <artifactId>spring-boot-starter-integration</artifactId>
  5.     </dependency>
  6.     <dependency>
  7.         <groupId>org.springframework.boot</groupId>
  8.         <artifactId>spring-boot-starter-web</artifactId>
  9.     </dependency>
  10.     <dependency>
  11.         <groupId>org.springframework.integration</groupId>
  12.         <artifactId>spring-integration-zookeeper</artifactId>
  13.     </dependency>
  14.     <dependency>
  15.         <groupId>org.springframework.integration</groupId>
  16.         <artifactId>spring-integration-redis</artifactId>
  17.     </dependency>
  18.     <dependency>
  19.         <groupId>org.springframework.boot</groupId>
  20.         <artifactId>spring-boot-starter-data-redis</artifactId>
  21.     </dependency>
  22. </dependencies>
复制代码


  • 设置
  1. # 端口随意改几个,分别启动,模拟多个实例
  2. server.port=12010
  3. spring.redis.host=192.168.56.10
复制代码


  • Redis锁设置类
  1. package com.ideax.lock.plus.config;
  2. import org.springframework.context.annotation.Bean;
  3. import org.springframework.context.annotation.Configuration;
  4. import org.springframework.data.redis.connection.RedisConnectionFactory;
  5. import org.springframework.integration.redis.util.RedisLockRegistry;
  6. /**
  7. * Redis锁配置类
  8. *
  9. * @author zhangxs
  10. **/
  11. @Configuration
  12. public class RedisLockConfiguration {
  13.     @Bean
  14.     public RedisLockRegistry redisLockRegistry(RedisConnectionFactory redisConnectionFactory) {
  15.         return new RedisLockRegistry(redisConnectionFactory, "redis-lock");
  16.     }
  17. }
复制代码


  • Zookeeper锁设置类
  1. package com.ideax.lock.plus.config;
  2. import org.apache.curator.framework.CuratorFramework;
  3. import org.springframework.context.annotation.Bean;
  4. import org.springframework.context.annotation.Configuration;
  5. import org.springframework.integration.zookeeper.config.CuratorFrameworkFactoryBean;
  6. import org.springframework.integration.zookeeper.lock.ZookeeperLockRegistry;
  7. /**
  8. * Zk锁配置类
  9. *
  10. * @author zhangxs
  11. **/
  12. @Configuration
  13. public class ZkLockConfiguration {
  14.     @Bean
  15.     public CuratorFrameworkFactoryBean curatorFrameworkFactoryBean() {
  16.         return new CuratorFrameworkFactoryBean("10.18.28.115:2181");
  17.     }
  18.     @Bean
  19.     public ZookeeperLockRegistry zookeeperLockRegistry(CuratorFramework curatorFramework) {
  20.         return new ZookeeperLockRegistry(curatorFramework, "/zookeeper-lock");
  21.     }
  22. }
复制代码


  • 测试代码
  1. package com.ideax.lock.plus.controller;
  2. import org.springframework.beans.factory.annotation.Autowired;
  3. import org.springframework.integration.redis.util.RedisLockRegistry;
  4. import org.springframework.integration.zookeeper.lock.ZookeeperLockRegistry;
  5. import org.springframework.web.bind.annotation.GetMapping;
  6. import org.springframework.web.bind.annotation.RequestMapping;
  7. import org.springframework.web.bind.annotation.RestController;
  8. import java.util.concurrent.TimeUnit;
  9. import java.util.concurrent.locks.Lock;
  10. /**
  11. * 锁测试接口
  12. *
  13. * @author zhangxs
  14. **/
  15. @RestController
  16. @RequestMapping("lock")
  17. public class LockController {
  18.     @Autowired
  19.     private RedisLockRegistry redisLockRegistry;
  20.     @Autowired
  21.     private ZookeeperLockRegistry zookeeperLockRegistry;
  22.     @GetMapping("redis")
  23.     public void redisDual() {
  24.         businessMethod(redisLockRegistry.obtain("redis"));
  25.     }
  26.     @GetMapping("zk")
  27.     public void zkDual() {
  28.         businessMethod(zookeeperLockRegistry.obtain("zookeeper"));
  29.     }
  30.     protected void businessMethod(Lock lock) {
  31.         try {
  32.             if (lock.tryLock(3, TimeUnit.SECONDS)) {
  33.                 System.out.println("锁对象就绪...");
  34.                 TimeUnit.SECONDS.sleep(5);
  35.             }
  36.         } catch (InterruptedException ie) {
  37.             System.out.println("锁获取失败...");
  38.             ie.printStackTrace();
  39.         } finally {
  40.             lock.unlock();
  41.         }
  42.     }
  43. }
复制代码


  • 启动多个实例,发哀求看测试效果
1、短时间内对12008和12009端口下redis接口发出哀求:


2、…12008/lock/redis的哀求先拿到锁:

3、…12009/lock/redis的哀求获取锁失败:

由此可证实,Redis分布式锁见效。
4、短时间内对12008和12009端口下zk接口发出哀求:


5、…12009/lock/zk的哀求先拿到锁:

6、…12010/lock/zk的哀求获取锁失败:

由此可证实,Zookeeper分布式锁见效。
四、总结

个人非常保举这种实现方式,更加机动。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x

帖子地址: 

回复

使用道具 举报

分享
推广
火星云矿 | 预约S19Pro,享500抵1000!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

草根技术分享(草根吧)是全球知名中文IT技术交流平台,创建于2021年,包含原创博客、精品问答、职业培训、技术社区、资源下载等产品服务,提供原创、优质、完整内容的专业IT技术开发社区。
  • 官方手机版

  • 微信公众号

  • 商务合作