redisson中分布式锁一定要加leaseTime

  |   0 评论   |   289 浏览

背景

最近项目中redis加锁失败,出现了attempt to unlock lock, not locked by current thread by node id: f4b01cb0-f7c6-4ce7-b6a1-6c09ca56c597 thread-id异常,导致tryLock里面的方法没有执行,引起了事故。

分析

以下是伪代码

RedissonClient redission = redissonComponent.getRedisson();
String key = RedisConstant.getKey("testLock");
    RLock lock = redission.getLock(key);
    try {
        //30秒内,只能有一个线程触发
        if (lock.tryLock(30, TimeUnit.SECONDS)) {
           //我是执行代码
        }
    } catch (Exception e) {
        logger.error("异常", e);
    } finally {
        lock.unlock();
    }

这个代码已经在线上执行了很久了,突然就出现问题了,首先想到的是是不是redis出现问题了,看了下网络和状态都是正常的。然后看lock.unlock的方法,异常就是从这里抛出来的:
image.png
是因为等了30秒,没有获取到锁,所以抛出来,这里去解锁的时候需要判断当前线程是否有锁。

if(lock.isLocked()){
 lock.unlock();
}

这样就不会抛异常了,但是还是没有解决加锁失败的问题。继续查看redisson的源码,发现如果不设置leaseTime的话,那么锁的key是不会过期的,如代码:
image.png
image.png
image.png
在查看redis里面的key,结果如下:

ip:6389[1]> hgetall testLock 
adc001e3-89b4-4e40-bc64-e45f7f027d42:293
1
ip:6389[1]> pttl testLock
24204
ip:6389[1]> pttl testLock
21096
ip:6389[1]> pttl testLock
29175
ip:6389[1]> pttl testLock
20325
ip:6389[1]> pttl testLock
28518

发现testLock的过期时间一直在刷新,这就导致其他线程加锁不成功。

解决

1、使用的时候加个leaseTime;
2、解锁的时候判断下锁是否还在;

RedissonClient redission = redissonComponent.getRedisson();
String key = RedisConstant.getKey("testLock");
    RLock lock = redission.getLock(key);
    try {
        //30秒内,只能有一个线程触发
        if (lock.tryLock(30,30, TimeUnit.SECONDS)) {
           //我是执行代码
        }
    } catch (Exception e) {
        logger.error("异常", e);
    } finally {
        if(lock.isLocked()){
            lock.unlock();
	}
    }

也可以关注我的公众号:程序之声
图片
关注公众号,领取更多资源

本文为博主原创文章,未经博主允许不得转载。

评论

发表评论