Redisson 分布式锁加锁注意事项

不废话直接上代码,具体情况请看注释


import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.concurrent.TimeUnit;

@Slf4j
@SpringBootTest
class StudyApplicationTests {
    @Autowired
    private RedissonClient redissonClient;

    @Test
    public void testRLock() {
        //需要加锁的key
        String lock_key = "lock_key";
        RLock rLock = redissonClient.getLock("lock_key");
        boolean locked = false;
        try {
            // 1. 传递了锁的有效时间,并且不等于-1,则到期之后直接锁失效(因为redis会自动删除到期的这个key)
            //    可能会出现,业务还没有处理完毕,还没有到达显式解锁的地步,锁就已经释放了,而且此时再去显式的释放锁会报异常[IllegalMonitorStateException]
            // 2. 不传递锁的有效时间,或者直接传递-1的情形下,锁的过期时间默认会置为30秒,并且激活看门狗的机制
            //    在默认情况下,看门狗会每隔10秒给这个key续期一次 也就是默认值/3   默认值可配
            //等待3秒,能够加上锁就加,加不上就放弃
            locked = rLock.tryLock(3,  TimeUnit.SECONDS);
            if (locked) {
                log.info("{}:加锁成功,开始处理业务", lock_key);
                //模拟处理业务逻辑10秒
                TimeUnit.SECONDS.sleep(10);
                log.info("{}:业务处理完毕", lock_key);
            } else {
                log.error("{}:未能成功获取到锁,无法处理此业务", lock_key);
            }
        } catch (InterruptedException e) {
            log.error("{}:尝试加锁过程中出现异常", lock_key);
        } finally {
            //如果当前线程并没有获取到锁的情况下,直接解锁会有异常存在,安全起见,try catch
            //可以根据上面的 locked 来判断是不是需要执行解锁,但是判断了之后,因为某些原因, 该key在redis中还是没了,也会有异常
            //总之 执行unlock 在没有锁的情况下执行会 IllegalMonitorStateException,双重判断
            if (locked) {
                try {
                    rLock.unlock();
                    log.info("{}:成功释放锁", lock_key);
                } catch (Exception e) {
                    log.error("锁释放失败:{},原因:{}", lock_key, e.getMessage());
                }
            }
        }

    }
}

下面分别测试 分别试试 传递时间和不传递时间的执行日志的过程

第一种 不传递时间 
locked = rLock.tryLock(3,  TimeUnit.SECONDS);
执行的日志输出
lock_key:加锁成功,开始处理业务
lock_key:业务处理完毕
lock_key:成功释放锁

第二种 传递时间,传递一个比业务逻辑长的时间
locked = rLock.tryLock(3, 15, TimeUnit.SECONDS);
执行的日志输出
lock_key:加锁成功,开始处理业务
lock_key:业务处理完毕
lock_key:成功释放锁

第三种 传递时间, 传递一个比业务逻辑短的时间
locked = rLock.tryLock(3, 5, TimeUnit.SECONDS);
执行的日志输出
lock_key:加锁成功,开始处理业务
lock_key:业务处理完毕
锁释放失败:lock_key,原因:attempt to unlock lock, not locked by current thread by node id: f33ca091-7909-49c5-aeec-afa701e3c5f1 thread-id: 1

结论:
如果很清楚自己的业务大约多长时间能执行结束的话,可以给一个明确的时间
如果不确定的话,就不要加key的有效期了
Redisson的看门狗帮我们处理这个问题,自动续期,然后我们记得显式解锁

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值