一、原生SetNx实现逻辑问题分析
1.1 示例代码
String value = UUID.randomUUID().toString();
Boolean aBoolean = redisTemplate.opsForValue().setIfAbsent(key, value, milliseconds, TimeUnit.MILLISECONDS);
try {
if (aBoolean) {
System.out.println("处理业务逻辑");
}
} finally {
String cacheValue = redisTemplate.opsForValue().get(key);
if (Objects.equals(value, cacheValue)) {
redisTemplate.delete(key);
}
}
1.2 示例代码分析
- 锁无法续期,最终不能保证排它性
- 释放锁非原子操作
- 不支持重入
二、Redisson锁实现
1、Lua脚本,key是我们传递过来的加锁的key,ARGV[2]是锁的名称线程ID,ARGV[1]锁的过期时间,默认30s
第一个if是加锁成功的逻辑,第二个if是锁的重入逻辑,最后是加锁失败,并返回锁的剩余时间。
2、加锁成功后构造锁续命数据,对象中是个Map
1、获取锁失败失败的线程,订阅释放锁的通道,加入等待队列中,等待被唤醒
释放锁逻辑