public class RedisLocked {
@Autowired
private RedisTemplate<String,String> redisTemplate;
@GetMapping("testLock")
public void testLocked(){
String locKey = "lock";
String uuid = UUID.randomUUID().toString();
Boolean lock = redisTemplate.opsForValue().setIfAbsent(locKey, uuid, 2, TimeUnit.SECONDS);
if(lock){
String value = redisTemplate.opsForValue().get("num");
if(StringUtils.isEmpty(value)){
return;
}
int num = Integer.parseInt(value + "");
redisTemplate.opsForValue().set("num", String.valueOf(++num));
// 问题:如果上一行卡顿3秒,而lock 是2秒过期,导致2秒后其他进程拿到锁,而再过1秒后这里删除的是其他进程拿的锁
// redisTemplate.delete(locKey);
// 利用UUID判断,解决上面的问题
/*if(uuid.equals(redisTemplate.opsForValue().get(locKey))){
// 新问题:如果进入这一行代码即将执行下面的删除操作,但是lock正好过期了,导致下面删除的依然是其他进程拿到的锁
redisTemplate.delete(locKey);
}*/
/*使用 lua 脚本来解决上面出现的问题*/
// 定义 lua 脚本
String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
// 使用 redis 执行 lua 执行
DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>();
redisScript.setScriptText(script);
// 设置一下返回值类型 为 Long
// 因为删除判断的时候,返回的 0,给其封装为数据类型。如果不封装那么默认返回 String 类型,
// 那么返回字符串与 0 会有发生错误。
redisScript.setResultType(Long.class);
// 第一个要是 script 脚本 ,第二个需要判断的 key,第三个就是 key 所对应的值。
redisTemplate.execute(redisScript, Arrays.asList(locKey), uuid);
}else {
try {
Thread.sleep(200);
testLocked();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
Redis分布式锁
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。
相关阅读更多精彩内容
- 首先分布式锁和我们平常讲到的锁原理基本一样,目的就是确保,在多个线程并发时,只有一个线程在同一刻操作这个业务或者说...
- 首先分布式锁和我们平常讲到的锁原理基本一样,目的就是确保,在多个线程并发时,只有一个线程在同一刻操作这个业务或者说...
- 首先分布式锁和我们平常讲到的锁原理基本一样,目的就是确保,在多个线程并发时,只有一个线程在同一刻操作这个业务或者说...
- 分布式锁我们在开发应用的时候,如果需要对某一个共享变量进行多线程同步访问的时候,可以使用我们学到的锁进行处理,并且...
- redis分布式锁切面实现 # 说明 网上找了一部分aop实现分布式锁的设计,感觉都不是特别好用,就自己写了一份。...