一、springboot项目整合redisson
- pom依赖如下
<!--redis分布式锁-->
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-boot-starter</artifactId>
<version>3.17.0</version>
</dependency>
- yml配置文件中的redis配置如下
spring:
redis:
host: 127.0.0.1
port: 6379
lettuce:
pool:
max-active: 50
max-wait: 30000ms
max-idle: 8
min-idle: 5
password: 123456
database: 11
- 配置RedissonClient
@Slf4j
@Configuration
public class RedisSonConfig {
@Value("${spring.redis.host}")
private String host;
@Value("${spring.redis.port}")
private String port;
@Value("${spring.redis.password}")
private String password;
@Bean
public RedissonClient redissonClient(){
try {
Config config = new Config();
//单节点
//redisSon版本是3.5,ip前面要加上“redis://”,不然会报错,3.2版本可不加
config.useSingleServer().setAddress("redis://" + host + ":" + port);
if (StringUtils.isBlank(password)) {
config.useSingleServer().setPassword(null);
} else {
config.useSingleServer().setPassword(password);
}
return Redisson.create(config);
}catch (RuntimeException e){
log.error("Redis连接失败:",e);
throw new RuntimeException("Redis连接失败");
}
}
@Bean
public RedissonConnectionFactory redissonConnectionFactory(RedissonClient redissonClient) {
return new RedissonConnectionFactory(redissonClient);
}
/**
* 分布式锁实例化并交给工具类
* @param redissonClient
*/
@Bean
public DistributedLockerImpl redissonLocker(RedissonClient redissonClient) {
DistributedLockerImpl locker = new DistributedLockerImpl(redissonClient);
RedisSonLockUtils.setLocker(locker);
return locker;
}
}
二、利用Redisson实现分布式锁
- 创建DistributedRedisLock类,代码如下
public interface DistributedLocker {
//可重入锁(Reentrant Lock)
//lock(), 拿不到lock就不罢休,不然线程就一直block
RLock lock(String lockKey);
//leaseTime为加锁时间,单位为秒
RLock lock(String lockKey, long timeout);
//timeout为加锁时间,时间单位由unit确定
RLock lock(String lockKey, long timeout, TimeUnit unit);
//公平锁(Fair Lock)
//lock(), 拿不到lock就不罢休,不然线程就一直block
RLock fairLock(String lockKey);
//leaseTime为加锁时间,单位为秒
RLock fairLock(String lockKey, long timeout);
//timeout为加锁时间,时间单位由unit确定
RLock fairLock(String lockKey, long timeout, TimeUnit unit);
//tryLock(),马上返回,拿到lock就返回true,不然返回false。
//带时间限制的tryLock(),拿不到lock,就等一段时间,超时返回false.
boolean tryLock(String lockKey, long waitTime, long leaseTime, TimeUnit unit);
//tryLock(),马上返回,拿到lock就返回true,不然返回false。
//带时间限制的tryLock(),拿不到lock,就等一段时间,超时返回false.【单位秒】
boolean tryLock(String lockKey, long waitTime, long leaseTime);
//tryLock(),马上返回,拿到lock就返回true,不然返回false。【至少一秒】
//带时间限制的tryLock(),等待1秒钟,超时返回false.
boolean tryLock(String lockKey, long leaseTime);
//tryLock(),马上返回,拿到lock就返回true,不然返回false。
//带时间限制的tryLock(),拿不到lock,就等一段时间,超时返回false.【单位秒】
boolean fairTryLock(String lockKey, long waitTime);
//fairTryLock(),马上返回,拿到lock就返回true,不然返回false。【公平锁】
//带时间限制的tryLock(),拿不到lock,返回false.
boolean fairTryLock(String lockKey);
//释放指定key锁
void unlock(String lockKey);
//释放锁
void unlock(RLock lock);
}
@Slf4j
@Component
public class DistributedLockerImpl implements DistributedLocker {
private RedissonClient redissonClient;
public DistributedLockerImpl(RedissonClient redissonClient) {
this.redissonClient = redissonClient;
}
//lock(), 拿不到lock就不罢休,不然线程就一直block
@Override
public RLock lock(String lockKey) {
RLock lock = redissonClient.getLock(lockKey);
lock.lock();
return lock;
}
//leaseTime为加锁时间,单位为秒
@Override
public RLock lock(String lockKey, long leaseTime) {
RLock lock = redissonClient.getLock(lockKey);
lock.lock(leaseTime, TimeUnit.SECONDS);
return lock;
}
//timeout为加锁时间,时间单位由unit确定
@Override
public RLock lock(String lockKey, long timeout,TimeUnit unit) {
RLock lock = redissonClient.getLock(lockKey);
lock.lock(timeout, unit);
return lock;
}
//公平锁(Fair Lock)
//lock(), 拿不到lock就不罢休,不然线程就一直block
@Override
public RLock fairLock(String lockKey) {
RLock lock = redissonClient.getFairLock(lockKey);
lock.lock();
return lock;
}
//timeout为加锁时间,单位为秒
@Override
public RLock fairLock(String lockKey, long timeout) {
RLock lock = redissonClient.getFairLock(lockKey);
lock.lock(timeout, TimeUnit.SECONDS);
return lock;
}
//timeout为加锁时间,时间单位由unit确定
@Override
public RLock fairLock(String lockKey, long timeout,TimeUnit unit) {
RLock lock = redissonClient.getFairLock(lockKey);
lock.lock(timeout, unit);
return lock;
}
//tryLock(),马上返回,拿到lock就返回true,不然返回false。
//带时间限制的tryLock(),拿不到lock,就等一段时间,超时返回false.
@Override
public boolean tryLock(String lockKey, long waitTime, long leaseTime,TimeUnit unit) {
if (StringUtils.isBlank(lockKey)){
log.error("传递lockKey字符串为空,不能获得锁");
return false;
}
RLock lock = redissonClient.getLock(lockKey);
try {
return lock.tryLock(waitTime, leaseTime, unit);
} catch (InterruptedException e) {
return false;
}
}
//tryLock(),马上返回,拿到lock就返回true,不然返回false。【单位秒】
//带时间限制的tryLock(),拿不到lock,就等一段时间,超时返回false.
@Override
public boolean tryLock(String lockKey, long waitTime, long leaseTime) {
if (StringUtils.isBlank(lockKey)){
log.error("传递lockKey字符串为空,不能获得锁");
return false;
}
RLock lock = redissonClient.getLock(lockKey);
try {
return lock.tryLock(waitTime, leaseTime, TimeUnit.SECONDS);
} catch (InterruptedException e) {
return false;
}
}
//tryLock(),马上返回,拿到lock就返回true,不然返回false。【至少一秒】
//带时间限制的tryLock(),等待1秒钟,超时返回false.
@Override
public boolean tryLock(String lockKey, long leaseTime) {
if (StringUtils.isBlank(lockKey)){
log.error("传递lockKey字符串为空,不能获得锁");
return false;
}
RLock lock = redissonClient.getLock(lockKey);
try {
if (leaseTime<1){
leaseTime = 1L;
}
return lock.tryLock(1L, leaseTime, TimeUnit.SECONDS);
} catch (InterruptedException e) {
return false;
}
}
//tryLock(),马上返回,拿到lock就返回true,不然返回false。【单位秒】
//带时间限制的tryLock(),拿不到lock,就等一段时间,超时返回false.
@Override
public boolean fairTryLock(String lockKey, long waitTime) {
if (StringUtils.isBlank(lockKey)){
log.error("传递lockKey字符串为空,不能获得锁");
return false;
}
RLock lock = redissonClient.getFairLock(lockKey);
try {
return lock.tryLock(waitTime,TimeUnit.SECONDS);
} catch (InterruptedException e) {
return false;
}
}
//fairTryLock(),马上返回,拿到lock就返回true,不然返回false。【公平锁】
//带时间限制的tryLock(),拿不到lock,返回false.
@Override
public boolean fairTryLock(String lockKey) {
if (StringUtils.isBlank(lockKey)){
log.error("传递lockKey字符串为空,不能获得锁");
return false;
}
RLock lock = redissonClient.getFairLock(lockKey);
try {
return lock.tryLock();
} catch (Exception e) {
return false;
}
}
//释放指定key锁
@Override
public void unlock(String lockKey) {
if (StringUtils.isBlank(lockKey)){
log.error("传递lockKey字符串为空,不能进行解锁");
return;
}
RLock lock = redissonClient.getLock(lockKey);
if(lock.isLocked()){
if(lock.isHeldByCurrentThread()){
lock.unlock();
}
}
}
//释放锁
@Override
public void unlock(RLock lock) {
if (lock!=null){
if(lock.isLocked()){
if(lock.isHeldByCurrentThread()){
lock.unlock();
}
}
}
}
}
public class RedisSonLockUtils {
private static DistributedLocker locker;
public static void setLocker(DistributedLocker locker) {
RedisSonLockUtils.locker = locker;
}
//lock(), 拿不到lock就不罢休,不然线程就一直block
public static RLock lock(String lockKey) {
return locker.lock(lockKey);
}
//leaseTime为加锁时间,单位为秒
public static RLock lock(String lockKey, long leaseTime) {
return locker.lock(lockKey,leaseTime);
}
//timeout为加锁时间,时间单位由unit确定
public static RLock lock(String lockKey, long timeout,TimeUnit unit) {
return locker.lock(lockKey,timeout,unit);
}
//公平锁(Fair Lock)
//lock(), 拿不到lock就不罢休,不然线程就一直block
public static RLock fairLock(String lockKey) {
return locker.fairLock(lockKey);
}
//timeout为加锁时间,单位为秒
public static RLock fairLock(String lockKey, long timeout) {
return locker.fairLock(lockKey,timeout);
}
//timeout为加锁时间,时间单位由unit确定
public static RLock fairLock(String lockKey, long timeout,TimeUnit unit) {
return locker.fairLock(lockKey,timeout,unit);
}
//tryLock(),马上返回,拿到lock就返回true,不然返回false。
//带时间限制的tryLock(),拿不到lock,就等一段时间,超时返回false.
public static boolean tryLock(String lockKey, long waitTime, long leaseTime,TimeUnit unit) {
return locker.tryLock(lockKey,waitTime,leaseTime,unit);
}
//tryLock(),马上返回,拿到lock就返回true,不然返回false。
//带时间限制的tryLock(),拿不到lock,就等一段时间,超时返回false.【单位秒】
public static boolean tryLock(String lockKey,long waitTime, long leaseTime) {
return locker.tryLock(lockKey,waitTime,leaseTime);
}
//tryLock(),马上返回,拿到lock就返回true,不然返回false。【至少一秒】
//带时间限制的tryLock(),等待1秒钟,超时返回false.
public static boolean tryLock(String lockKey,long leaseTime) {
return locker.tryLock(lockKey,leaseTime);
}
//tryLock(),马上返回,拿到lock就返回true,不然返回false。【公平锁】
//带时间限制的tryLock(),拿不到lock,就等一段时间,超时返回false.
public static boolean fairTryLock(String lockKey, long waitTime) {
return locker.fairTryLock(lockKey,waitTime);
}
//tryLock(),马上返回,拿到lock就返回true,不然返回false。【公平锁】
//带时间限制的tryLock(),拿不到lock,返回false.
public static boolean fairTryLock(String lockKey) {
if (StringUtils.isBlank(lockKey)){
return false;
}
return locker.fairTryLock(lockKey);
}
//释放指定key锁
public static void unlock(String lockKey) {
if (StringUtils.isNotBlank(lockKey)){
locker.unlock(lockKey);
}
}
//释放锁
public static void unlock(RLock lock) {
if (lock!=null){
locker.unlock(lock);
}
}
}
三. 业务应用
@Transactional(rollbackFor = Exception.class)
@Override
public ResponseVO saveChatGroup() {
//群组id
String groupId = UUIDUtils.getUUID32();
RLock lock = null;
try {
lock = RedisSonLockUtils.fairLock(groupId);
}catch (Exception e){
}finally {
RedisSonLockUtils.unlock(lock);
}
}