在经过我们不断的改进后,可以说此时项目中的分布式锁是一个相对完善的锁,但依然存在着改进的空间。比如:
当前项目中的锁是不可重入的锁:同一个线程无法多次获取同一把锁,有时候我们会有这样的需求:A方法中需要获取锁并会调用同一个类中的方法B,同时在B方法中也需要获取锁,如果当前系统的锁不是可重入锁,那么就会造成死锁问题。
当前项目中的锁是不可重试的锁:当某个线程获取锁失败后,直接返回错误,该线程无法重试。
当前项目中的锁在Redis集群模式下可能存在问题:在Redis集群模式下,主从节点间存在一定的同步延迟,如果主节点宕机而从节点又未能及时同步存储在主节点中的锁信息,可能会导致线程安全问题。
以上几种问题可以自己实现解决方案,但是我们可以使用他人开发好的分布式框架——Redisson来解决以上问题,避免重复造轮子。Redisson是一个基于Redis的分布式框架。在解决以上问题的同时,Redisson实现的分布式锁利用watchdog机制实现了不断更新锁的有效期,避免因为线程阻塞而锁释放导致线程安全问题的出现
使用步骤:
- 引入Redisson依赖
1 2 3 4 5 6
| <dependency> <groupId>org.redisson</groupId> <artifactId>redisson</artifactId> <version>3.13.6</version> </dependency>
|
- 配置Redisson(有多种方式,这里使用的是配置类)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| package com.hmdp.config;
import org.redisson.Redisson; import org.redisson.api.RedissonClient; import org.redisson.config.Config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration;
@Configuration public class RedissonConfig { @Bean public RedissonClient getRedisson(){ Config config = new Config(); config.useSingleServer().setAddress("redis:192.168.21.128:6379").setPassword("dch");
return Redisson.create(config); } }
|
- 使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| RLock lock = redissonClient.getLock("lock:order:" + userId); boolean isLock = lock.tryLock(); if(!isLock){ return Result.fail("每个用户只能购买一次"); } try { ISeckillVoucherService currentProxy = (ISeckillVoucherService) AopContext.currentProxy(); return currentProxy.createVoucherOrder(id); } finally { lock.unlock(); }
|