赞
踩
目录
还是一个同事问的一个问题,然后闲着没事就记录下来了。多人操作同一个保单,会出现数据不一致,所以呢,就准备为此单子加一个锁,所以就有了下面的代码。分享给大家
分布式锁的定义大家基本都很了解了,具体就是当需要在分布式环境中保证资源的互斥访问或一致性时,就可以考虑使用分布式锁。但需要注意的是,分布式锁虽然可以解决问题,但也会带来一定的性能开销和复杂度,因此在使用时需要权衡系统的性能和可维护性,以及使用分布式锁所带来的成本和风险。
redisTemplate.opsForValue().setIfAbsent("redisLock", uuid, 1000, TimeUnit.SECONDS);
这段代码是使用Spring Data Redis的RedisTemplate
来执行一个Redis操作。具体来说,它尝试在Redis中设置一个键值对,但仅当该键不存在时。
详细解释如下:
"ruleRefreshLock"
:这是要设置的Redis键。uuid
:这是要设置的Redis值。1000
:这是值的过期时间,单位是毫秒。TimeUnit.SECONDS
:这是过期时间的单位,这里是秒。setIfAbsent
方法的行为如下:
"ruleRefreshLock"
在Redis中不存在,那么它会设置这个键的值为uuid
,并给这个键设置一个1000秒的过期时间。此时,setIfAbsent
方法返回true
。"ruleRefreshLock"
在Redis中已经存在,那么它不会做任何操作,并且setIfAbsent
方法返回false
。这个方法通常用于实现分布式锁。在这个例子中,你可能想要确保只有一个实例或线程能够获取到"ruleRefreshLock"这个锁。如果锁已经被其他实例或线程获取(即键已经存在),那么当前实例或线程就不会再尝试获取锁。如果锁未被获取(即键不存在),那么当前实例或线程就会获取锁,并设置一个过期时间以确保锁最终会被释放。
设置KEY值过期时间
- //假设 lockName 是你的锁的名称,expireTime 是你希望锁持续的时间(以分钟为单位)
- redisTemplate.expire(lockName, expireTime, TimeUnit.MINUTES);
这段代码是使用 RedisTemplate
来设置 Redis 中某个键的过期时间。这与之前的 setIfAbsent
操作有所不同,主要区别如下:
setIfAbsent
:true
;如果键已经存在,则不做任何操作并返回 false
。expire
:true
;如果键不存在,则不进行任何操作并返回 false
。假设你已经有了一个名为 lockName
的锁,并且这个锁已经被某个实例获取(即该键在 Redis 中已经存在)。你想让这个锁在一段时间后自动释放,那么你可以使用 expire
方法来设置锁的过期时间。
redis版本 spring-data-redis-2.7.10.jar
- @Slf4j
- @Component
- public class redisSchedule implements SchedulingConfigurer {
-
- @Value("${rule.limit.cron}")
- private String cron;
- @Value("${schedule.rule}")
- private String scheduleRule;
- @Autowired
- private StringRedisTemplate redisTemplate;
-
- @Override
- public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
- taskRegistrar.addCronTask(() -> {
- // 分布式锁,集群环境只允许一台服务修改定时任务
- String uuid = UUID.randomUUID().toString();
- Boolean bool = redisTemplate.opsForValue().setIfAbsent("redisLock", uuid, 1000, TimeUnit.SECONDS);
- try {
- if (bool) {
- //逻辑代码
- }
- } catch (Exception e) {
- log.error(e.getMessage());
- } finally {
- // 释放锁,先比对自己锁的值是否相等,相等则为自己的锁
- String script = "if redis.call('get',KEYS[1]) == ARGV[1] then return redis.call('del',KEYS[1]) else return 0 end";
- redisTemplate.execute(new DefaultRedisScript<Long>(script, Long.class), Arrays.asList("redisLock"), uuid);
- }
- }, cron);
- }
- }
redis版本 spring-data-redis-1.8.0.RELEASE.jar
- //锁的过期时间,默认为5分钟
- private Long expireTime = 5L;
-
- try {
- //多个执行任务去获得锁,如果没有获取证明还有任务在执行中,那么将不再执行任务
- Boolean isLock = redisTemplate.opsForValue().setIfAbsent(lockName, "lock");
- if (isLock){
- //获取到锁,那么设置过期时间,防止死锁
- this.redisTemplate.expire(lockName, expireTime, TimeUnit.MINUTES);
- //逻辑代码
- }else {
- logger.info("任务执行锁定失败,Lock被占用,当前分片:=====");
- throw new Exception("任务执行锁定失败");
- }
- } catch (Exception e) {
- e.printStackTrace();
- throw new Exception(e.getMessage());
- }
总结一下,setIfAbsent
用于在键不存在时设置键值对,并返回操作是否成功的布尔值;而 expire
用于设置或更新已存在键的过期时间,并返回操作是否成功的布尔值。这两个操作经常一起使用来实现分布式锁,其中 setIfAbsent
用于尝试获取锁,而 expire
用于设置锁的过期时间以确保锁最终会被释放。两种方式的用法看对应的应用场景来使用
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。