​ 在经过我们不断的改进后,可以说此时项目中的分布式锁是一个相对完善的锁,但依然存在着改进的空间。比如:

​ 当前项目中的锁是不可重入的锁:同一个线程无法多次获取同一把锁,有时候我们会有这样的需求:A方法中需要获取锁并会调用同一个类中的方法B,同时在B方法中也需要获取锁,如果当前系统的锁不是可重入锁,那么就会造成死锁问题。

​ 当前项目中的锁是不可重试的锁:当某个线程获取锁失败后,直接返回错误,该线程无法重试。

​ 当前项目中的锁在Redis集群模式下可能存在问题:在Redis集群模式下,主从节点间存在一定的同步延迟,如果主节点宕机而从节点又未能及时同步存储在主节点中的锁信息,可能会导致线程安全问题。

​ 以上几种问题可以自己实现解决方案,但是我们可以使用他人开发好的分布式框架——Redisson来解决以上问题,避免重复造轮子。Redisson是一个基于Redis的分布式框架。在解决以上问题的同时,Redisson实现的分布式锁利用watchdog机制实现了不断更新锁的有效期,避免因为线程阻塞而锁释放导致线程安全问题的出现

​ 使用步骤:

  1. 引入Redisson依赖
1
2
3
4
5
6
<!--        Redisson依赖-->
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>3.13.6</version>
</dependency>
  1. 配置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;

/**
* 配置Redisson
*/
@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. 使用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
RLock lock = redissonClient.getLock("lock:order:" + userId);
//可以设置锁的重试时间(默认为-1表示不允许重试)、超时时间(默认30秒)
boolean isLock = lock.tryLock();
if(!isLock){
return Result.fail("每个用户只能购买一次");
}
try {
//获取代理对象,避免自身调用导致事务失效
ISeckillVoucherService currentProxy = (ISeckillVoucherService) AopContext.currentProxy();
return currentProxy.createVoucherOrder(id);
} finally {
//释放锁
lock.unlock();
}