Redis分布式锁实现原理
Redis分布式锁的实现原理主要是基于Redis的单线程模型和SETNX命令,先来简单介绍一下:
- Redis是单线程模型,每个请求都是按顺序执行的,保证了操作的原子性。
- SETNX命令是Redis提供的原子性操作,可以将一个key的值设为value,当且仅当该key不存在,即实现了互斥锁的功能。
基于以上两点,我们可以使用Redis实现分布式锁的功能:
- 在Redis中创建一个key,作为锁的标识。
- 使用SETNX命令将该key的值设为某个固定值,如果返回结果为1,则表示获取了锁,否则表示锁已被其他客户端占用。
- 在获取锁之后,进行业务处理。
- 业务处理完毕后,使用DEL命令删除该key,释放锁。
Redis分布式锁代码框架
以下是一个基于Redis实现分布式锁的代码框架,使用了AOP实现自动加锁和解锁。
Redis分布式锁配置信息
spring:
redis:
host: localhost
port: 6379
database: 0
password:
timeout: 10000
lettuce:
pool:
max-active: 8
max-idle: 8
min-idle: 0
max-wait: -1ms
Redis分布式锁工具类
@Component
public class RedisLockUtil {
private final RedisTemplate<String, String> redisTemplate;
public RedisLockUtil(RedisTemplate<String, String> redisTemplate) {
this.redisTemplate = redisTemplate;
}
/**
* 获取锁
*
* @param key 锁标识
* @param expireTime 锁过期时间
* @return 是否获取锁成功
*/
public boolean lock(String key, long expireTime) {
Boolean result = redisTemplate.opsForValue().setIfAbsent(key, "1", expireTime, TimeUnit.MILLISECONDS);
return result != null && result;
}
/**
* 释放锁
*
* @param key 锁标识
*/
public void unlock(String key) {
redisTemplate.delete(key);
}
}
Redis分布式锁AOP切面
@Aspect
@Component
public class RedisLockAspect {
private final RedisLockUtil redisLockUtil;
public RedisLockAspect(RedisLockUtil redisLockUtil) {
this.redisLockUtil = redisLockUtil;
}
@Pointcut("@annotation(com.example.demo.annotation.RedisLock)")
public void redisLockPointcut() {
}
@Around("redisLockPointcut()")
public Object redisLockAround(ProceedingJoinPoint joinPoint) throws Throwable {
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
RedisLock redisLock = method.getAnnotation(RedisLock.class);
String lockKey = redisLock.key();
long expireTime = redisLock.expireTime();
boolean lock = redisLockUtil.lock(lockKey, expireTime);
if (!lock) {
throw new RuntimeException("获取锁失败");
}
try {
return joinPoint.proceed();
} finally {
redisLockUtil.unlock(lockKey);
}
}
}
Redis分布式锁注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface RedisLock {
/**
* 锁标识
*/
String key();
/**
* 锁过期时间,默认为5秒
*/
long expireTime() default 5000;
}
Redis分布式锁测试代码
@SpringBootTest
class RedisLockUtilTest {
@Autowired
private RedisLockUtil redisLockUtil;
@Test
void lock() {
boolean lock = redisLockUtil.lock("test", 5000);
System.out.println(lock);
}
@Test
@RedisLock(key = "test")
void test() throws InterruptedException {
System.out.println("业务处理中...");
Thread.sleep(3000);
System.out.println("业务处理完成");
}
}
结果展示
执行测试代码后,控制台输出如下:
true
业务处理中...
业务处理完成
以上就是一个基于Redis实现分布式锁的代码框架,使用了AOP实现自动加锁和解锁。