redission锁的几个问题

redissonClient.getlock()这个方法获取锁时,有几个问题没弄明白
1、锁一直被其他服务占用,但是因为redission存在看门口机制,会不断刷新锁的时间,导致锁一直被占用,此时其他线程getLock方法会怎么样?一直被阻塞嘛?还是到一定时间会自动抛出无法获取到锁?
2、此时如果原来的线程一直在运行,是不是当前锁会因为看门狗机制一直刷新过期时间,导致其他服务一直无法获取到锁?

不知道你这个问题是否已经解决, 如果还没有解决的话:
  • 这篇博客: Redisson & RedLock分布式锁中的 1.1.4 针对高并发的问题,该怎么解决?? 部分也许能够解决你的问题, 你可以仔细阅读以下内容或者直接跳转源博客中阅读:

    本质在于我自己的加的锁,结果会被别的线程给删掉,对不对。

    接下来我们能想到的办法就是给这个锁加一个唯一标志。把id加到锁里边去。

    String uniqueId = UUID.randomUUID.toString() + threadId;
    

    当我们要解锁的时候判断一下,加锁的id是否是我本人加的

    String uniqueId = UUID.randomUUID.toString() + threadId;
    try{
        String lockKey = "lockKey";
        Boolean result = redisTemplate.opsForValue().setIfAbsent(lockKey,uniqueId, "hello",10,TimeUnit.SECONDS);
        
        if(!result){
        	return "something exception";
        }
        	// 大量业务代码
        	...
    }
    finally{ 
        if(uniqueId.equals(redisTemplate.opsForValue().get(lockKey))){
        	redisTemplate. delete(lockKey);
        }
    }
    return "program End ...";
    

    当执行到这儿,还是有点问题哈,如果程序执行15秒才结束,但是10秒锁才释放。还是会有并发的问题。

    时间不是解决问题的方案,还有没有别的思路?
    在redis的处理方式上确实有实现方法:在此现况的情景下,通过定时器去扫,分线程每过10秒扫一次,判断一下主线程是否持有锁,key是否还存在,如果存在,把超时时间再设置长一点,跟token续期类似。

  • 以下回答来自chatgpt:

    根据参考资料中提到的内容,可以给出以下解答和优化建议:

    1. 当锁一直被其他服务占用时,使用redissonClient.getLock()方法获取锁的其他线程会一直被阻塞,而不会自动抛出无法获取到锁的异常。因为Redisson中的分布式锁实现了看门狗机制,会定时刷新锁的过期时间。所以其他线程会一直等待锁被释放,直到超过锁的过期时间才会放弃获取锁的尝试。为了避免其他线程一直阻塞,可以使用tryLock()方法,设置一个获取锁的超时时间,超过该时间后如果仍然无法获取到锁,就可以进行其他处理。

    示例代码:

    RLock lock = redissonClient.getLock("myLock");
    boolean isLocked = lock.tryLock(10, TimeUnit.SECONDS);
    if (isLocked) {
        try {
            // 执行业务逻辑
        } finally {
            lock.unlock();
        }
    } else {
        // 锁获取超时的处理逻辑
    }
    
    1. 在锁被其他服务占用且原来的线程一直在运行的情况下,看门狗机制会不断刷新锁的过期时间,导致其他服务一直无法获取到锁。这是预期的行为,因为分布式锁的目的是保证在分布式环境下只有一个线程能够执行关键代码区域,其他线程需要等待。如果其他服务一直无法获取到锁,说明原来的线程一直在执行关键代码,并不会导致其他服务的异常。如果确实需要其他服务能够获取到锁,可以考虑增加监听器,在原来的线程执行完关键代码后手动释放锁。

    示例代码:

    RLock lock = redissonClient.getLock("myLock");
    try {
        lock.lock();
        // 执行关键代码
        // 释放锁
        lock.unlock();
    } finally {
        lock.unlock();
    }
    

    优化建议: - 在创建锁对象时,可以使用配置的分布式锁定时是否自动续期,以避免锁过期时间不足导致并发问题。 - 对于需要长时间锁定的关键代码,可以考虑将锁的持有时间设置得更长,或者在关键代码执行前手动续期锁的过期时间。 - 如果允许其他服务能够获取到锁,可以在关键代码执行完后手动释放锁,而不是依赖看门狗机制自动释放锁。

    注意:以上建议是根据参考资料中提到的Redission框架和RedLock算法给出的解决方案,具体的实现细节还需要根据具体情况和业务需求进行调整。如果需要更多详细的实现代码和配置信息,请提供相关环境和业务场景的详细信息。


如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^