Springboot利用Redis实现分布式锁

打印 上一主题 下一主题

主题 881|帖子 881|积分 2643

1、利用场景和实现方案:

利用场景:本地锁如Lock和Syncronized只能锁住本地进程,在分布式应用中,必要利用分布式锁来更好实现特定的业务。
实现方案:有多种,比如利用mysql、zookeeper、redis,各种方案有其优缺点,利用哪种方式需结合具体业务来选择。下面先容一下利用redis实现分布式锁。
实现方式:如下图所示

具体实现代码:
2.1 利用redisTemplate:
  1.     public Map<String,  List<Catelog2Vo>> getCatelogJsonFromDbWithRedisLock()  {
  2.         //使用redis分布式锁,防止缓存击穿
  3.         String uuid = UUID.randomUUID().toString();
  4.         Boolean lock = redisTemplate.opsForValue().setIfAbsent("lock", uuid,300,TimeUnit.SECONDS);
  5.         Map<String, List<Catelog2Vo>>map;
  6.         if(lock){
  7.             //如果加锁成功,执行业务
  8.             System.out.println("获取分布式锁成功...........");
  9.             map = getDataFromDb();
  10.             try {
  11.             } finally {
  12.                 //执行完业务,要释放锁,使用delete解锁,非原子性,存在缺陷
  13.                 // 获取值对比+对比成功删除=原子操作
  14.                 // String lockValue = redisTemplate.opsForValue().get("lock");
  15.                 // if (uuid.equals(lockValue)) {
  16.                 //     redisTemplate.delete("lock");
  17.                 // }
  18.                 // 使用lua脚本解锁,保证原子性
  19.                 String script = "if redis.call('get',KEYS[1]) == ARGV[1] then return redis.call('del',KEYS[1]) else return 0 end";
  20.                 Long unlock = redisTemplate.execute(new DefaultRedisScript<Long>(script, Long.class), Arrays.asList("lock"), uuid);
  21.             }
  22.             return map;
  23.         }else{
  24.             //加锁失败,重试,执行类似syncronized方法,自旋锁,等待->重试
  25.             System.out.println("获取分布式锁失败........等待重试");
  26.             //可以添加休眠时间
  27.             try {
  28.                 Thread.sleep(100);
  29.             } catch (InterruptedException e) {
  30.                 throw new RuntimeException(e);
  31.             }
  32.             return this.getCatelogJsonFromDbWithRedisLock();
  33.         }
  34.     }
复制代码
 2.2 利用Redisson 实现分布式锁:
Redisson 是架设在 Redis 底子上的一个 Java 驻内存数据网格(In-Memory Data Grid) 。 充分的利用了 Redis 键值数据库提供的一系列上风, 基于 Java 实用工具包中常用接口, 为利用者提供了一系列具有分布式特性的常用工具类。 使得原来作为协调单机多线程并发程序的工具包得到了协调分布式多机多线程并发体系的能力, 大大降低了设计和研发大规模分布式体系的难度。 同时结合各富特色的分布式服务, 更进一步简化了分布式环境中程序相互之间的协作。
官方文档: https://github.com/redisson/redisson/wiki/%E7%9B%AE%E5%BD%95
利用方法:
1、maven引入依靠
  
  1. <!--使用redisson作为所有分布式锁,分布式对象等功能框架-->
  2. <dependency>
  3.      <groupId>org.redisson</groupId>
  4.      <artifactId>redisson</artifactId>
  5.      <version>3.12.0</version>
  6. </dependency>
复制代码
2、 配置:
  1. // 默认连接地址 127.0.0.1:6379
  2. RedissonClient redisson = Redisson.create();
  3. Config config = new Config(); //redis://127.0.0.1:7181
  4. //可以用"rediss://"来启用 SSL 连接
  5. config.useSingleServer().setAddress("redis://192.168.56.10:6379");
  6. RedissonClient redisson = Redisson.create(config);
复制代码
3、 利用分布式锁
  1. RLock lock = redisson.getLock("anyLock");// 最常见的使用方法
  2. lock.lock();
  3. // 加锁以后 10 秒钟自动解锁// 无需调用 unlock 方法手动解锁
  4. lock.lock(10, TimeUnit.SECONDS);
  5. // 尝试加锁, 最多等待 100 秒, 上锁以后 10 秒自动解锁
  6. boolean res = lock.tryLock(100,10, TimeUnit.SECONDS);
  7. if (res) {
  8. try {
  9.    
  10.    ...
  11. } finally {
  12.    lock.unlock();
  13.   }
  14. }
复制代码


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

正序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

农民

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表