基于setnx实现的分布式锁存在下面的问题:
1.不可重入
同一个线程无法多次获取同一把锁
2.不可重试
获取锁只尝试一次就返回false,没有重试机制
3.超时释放
锁超时释放虽然可以避免死锁,但如果是业务执行耗时较长,也会导致锁释放,存在安全隐患
4.主从一致性(主写从读)
如果Redis提供了主从集群,主从同步存在延迟,当主宕机时,如果从并同步主中的锁数据,则会出现锁实现
Redission
Redisson是一 个在Redis的基础.上实现的ava驻内存数据网格(In-Memory Data Grid) 。它不仅提供了一系列的分布式的Java常用对象,还提供了许多分布式服务,其中就包含了各种分布式锁的实现。
官网地址: https://redisson.org/
GitHub地址: https://github.com/redisson/redisson
引入依赖
<!--redisson-->
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>3.13.6</version>
</dependency>
配置redisson java客户端
@Configuration
public class RedissonConfig {
@Bean
public RedissonClient redissonClient(){
// 配置
Config config = new Config();
config.useSingleServer().setAddress("redis://192.168.40.128:6379").setPassword("root");
// 创建RedissonClient对象
return Redisson.create(config);
}
}
使用redisson的分布式锁
private void createVoucherOrder(VoucherOrder voucherOrder) {
Long userId = voucherOrder.getUserId();
Long voucherId = voucherOrder.getVoucherId();
// 创建锁对象
RLock redisLock = redissonClient.getLock("lock:order:" + userId);
// 尝试获取锁
boolean isLock = redisLock.tryLock();
// 判断
if (!isLock) {
// 获取锁失败,直接返回失败或者重试
log.error("不允许重复下单!");
return;
}
}
可重入锁
什么是可重入锁?
https://blog.csdn.net/u014571143/article/details/126357814
@Slf4j
@SpringBootTest
class RedissonTest {
@Resource
private RedissonClient redissonClient;
private RLock lock;
@BeforeEach
void setUp() {
lock = redissonClient.getLock("order");
}
@Test
void method1() throws InterruptedException {
// 尝试获取锁
boolean isLock = lock.tryLock(1L, TimeUnit.SECONDS);
if (!isLock) {
log.error("获取锁失败 .... 1");
return;
}
try {
log.info("获取锁成功 .... 1");
method2();
log.info("开始执行业务 ... 1");
} finally {
log.warn("准备释放锁 .... 1");
lock.unlock();
}
}
void method2() {
// 尝试获取锁
boolean isLock = lock.tryLock();
if (!isLock) {
log.error("获取锁失败 .... 2");
return;
}
try {
log.info("获取锁成功 .... 2");
log.info("开始执行业务 ... 2");
} finally {
log.warn("准备释放锁 .... 2");
lock.unlock();
}
}
}
使用的是Redis的hash数据结构,key为线程名称,value为获取锁的次数
watchDog机制
注意:只有超时释放时间为-1时,才会开启watchDog,如果提前设置了超时释放时间,不会开启watchDog
watchDog 默认续约时间是30秒
Redisson分布式锁原理:
●可重入:利用hash结构记录线程id和重入次数
●可重试:利用信号量和PubSub功能实现等待、唤醒,获取锁失败的重试机制
●超时续约:利用watchDog,每隔一段时间(releaseTime/3),重置超时时间
标签:redisson,log,lock,....,获取,isLock,优化,分布式 From: https://blog.51cto.com/AmbitionGarden/8011237