基于Redisson实现分布式锁
Redisson是一个在Redis的基础上实现的Java驻内存数据网格(In-Memory Data Grid);Redisson利用了Redis键值数据库提供的高性能和丰富的特性,实现了可扩展的分布式Java应用。
Redisson分布式锁实践:
- 典型的使用Redisson实现分布式锁的模板
- 工具类
- 注解实现分布式锁
1、典型的使用Redisson实现分布式锁的模板
- 引入Redisson依赖:首先在项目中引入Redisson的相关依赖,可以通过Maven或Gradle等构建工具来添加依赖。
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>3.16.2</version> <!-- 指定版本号 -->
</dependency>
- 初始化Redisson客户端:在代码中创建Redisson客户端实例,连接到Redis服务器。可以使用
Config
对象配置Redisson客户端的参数,如Redis服务器地址、密码等。
// 初始化Redisson客户端
Config config = new Config();
config.useSingleServer().setAddress("redis://127.0.0.1:6379");
RedissonClient redisson = Redisson.create(config);
-
获取分布式锁:通过Redisson客户端实例获取分布式锁对象,一般使用
getLock
方法获取一个RLock
对象,RLock提供了锁的基本操作方法。 -
加锁:在需要加锁的代码块中调用RLock对象的
lock
方法来获取锁。这会阻塞当前线程直到获取到锁为止。 -
执行业务逻辑:在获得锁之后,执行需要保护的业务逻辑。
-
释放锁:在业务逻辑执行完成后,调用RLock对象的
unlock
方法来释放锁。
示例代码如下:
import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
/**
* 分布式锁模板类,用于执行带锁的任务
*/
public class DistributedLockTemplate {
private final RedissonClient redissonClient;
/**
* 构造方法,初始化Redisson客户端
*/
public DistributedLockTemplate() {
Config config = new Config(); //创建一个 Redisson 的配置对象 Config 的实例
config.useSingleServer().setAddress("redis://127.0.0.1:6379");
this.redissonClient = Redisson.create(config);
}
/**
* 执行带锁的任务
* @param lockName 锁名称
* @param worker 执行任务的回调接口
* @return 任务执行结果
*/
public <T> T execute(String lockName, AquiredLockWorker<T> worker) {
RLock lock = redissonClient.getLock(lockName);
try {
lock.lock();
return worker.invokeAfterLockAquire();
} finally {
lock.unlock();
}
}
/**
* 任务执行的回调接口
* @param <T> 返回结果类型
*/
public interface AquiredLockWorker<T> {
T invokeAfterLockAquire();
}
}
DistributedLockTemplate
类:
- 这个类是一个模板类,封装了执行带锁任务的逻辑,并提供了一个统一的方法
execute
来执行带锁任务。 - 在构造方法中初始化了 Redisson 客户端,并且在每次执行带锁任务时都会获取到一个锁对象、加锁、执行任务、释放锁。
- 提供了一个接口
AquiredLockWorker
,用于定义执行任务的回调接口。
2、工具类
- 注解实现分布式锁
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import java.util.concurrent.TimeUnit;
/**
* 分布式锁工具类
*/
public class DistributedLockUtil {
private static RedissonClient redissonClient;
/**
* 设置 Redisson 客户端
*/
public static void setRedissonClient(RedissonClient client) {
redissonClient = client;
}
/**
* 尝试获取锁
* @param lockKey 锁的标识
* @param waitTime 等待时间
* @param leaseTime 锁的持有时间
* @param unit 时间单位
* @return 是否成功获取锁
*/
public static boolean tryLock(String lockKey, long waitTime, long leaseTime, TimeUnit unit) {
RLock lock = redissonClient.getLock(lockKey);
try {
return lock.tryLock(waitTime, leaseTime, unit);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
/**
* 释放锁
* @param lockKey 锁的标识
*/
public static void unlock(String lockKey) {
RLock lock = redissonClient.getLock(lockKey);
if (lock.isHeldByCurrentThread()) {
lock.unlock();
}
}
}
3、注解实现分布式锁
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
/**
* 切面类,用于处理分布式锁注解
*/
@Aspect
@Component
public class DistributedLockAspect {
/**
* 环绕通知,在被 @DistributedLock 注解的方法执行前后加锁和解锁操作
* @param joinPoint 切点
* @param distributedLock 分布式锁注解
* @return 方法执行结果
* @throws Throwable 异常
*/
@Around("@annotation(distributedLock)")
public Object around(ProceedingJoinPoint joinPoint, DistributedLock distributedLock) throws Throwable {
// 获取锁
RLock lock = RedissonLockUtil.getLock(distributedLock.value());
try {
lock.lock();
// 执行业务逻辑
return joinPoint.proceed();
} finally {
lock.unlock();
}
}
}
总结
基于Redisson实现分布式锁的主要实践方法包括典型的使用模板、工具类和注解实现。下面是这些方法的总结:
1. 典型的使用Redisson实现分布式锁的模板
在这种方法中,我们通过引入Redisson依赖、初始化Redisson客户端、获取分布式锁以及执行业务逻辑和释放锁来实现分布式锁的使用。典型的步骤包括:
- 引入Redisson依赖
- 初始化Redisson客户端
- 获取分布式锁
- 加锁
- 执行业务逻辑
- 释放锁
2. 工具类
通过封装工具类实现分布式锁的获取和释放,可以方便地在代码中调用。工具类提供了设置Redisson客户端、尝试获取锁、释放锁等方法,使得分布式锁的使用更加简洁和灵活。
3. 注解实现分布式锁
通过定义注解和切面类,在被注解的方法执行前后加锁和解锁操作,从而简化了分布式锁的应用。通过这种方法,可以通过注解的方式在方法上添加分布式锁,使得代码更加清晰和易于维护。
以上三种方法都是基于Redisson实现分布式锁的常见实践方式。
当面试官问如何基于Redisson实现分布式锁时,你可以回答以下几点:
-
引入Redisson依赖:首先需要在项目中引入Redisson的相关依赖,可以通过Maven或Gradle等构建工具来添加依赖。
-
初始化Redisson客户端:在代码中创建Redisson客户端实例,连接到Redis服务器。可以使用
Config
对象配置Redisson客户端的参数,如Redis服务器地址、密码等。 -
获取分布式锁:通过Redisson客户端实例获取分布式锁对象,一般使用
getLock
方法获取一个RLock
对象,RLock提供了锁的基本操作方法。 -
加锁和解锁:在需要加锁的代码块中调用RLock对象的
lock
方法来获取锁,然后在业务逻辑执行完毕后调用unlock
方法释放锁。 -
错误处理:对于获取锁的操作,需要考虑超时时间和异常情况的处理,确保系统的稳定性和可靠性。
-
可选的实现方式:除了基本的加锁和解锁操作外,还可以根据业务需求选择使用工具类或注解的方式来简化分布式锁的应用。
举例说明常见的实现方式,如使用模板类封装带锁任务的执行逻辑、编写工具类封装加锁和解锁操作、以及使用注解和切面类简化分布式锁的应用。
这样的回答能够展示出你对基于Redisson实现分布式锁的理解和实践经验,向面试官展示你的技术能力和经验。