当前位置: 首页>数据库>正文

Redis客户端工具 默认超时时间 redisson超时

1.问题引入, 生产现象.
mq突然有消息积压(有很多是业务上重复的消息), 按消费速度, 几个月估计才会消费完

  1. 主要涉及业务
    elasticjob去分页拉取外系统的数据(在一次任务中, 加全局锁, 然后进行单线程同步阻塞式的数据处理)

3.排查:
看了一下代码, 单线程同步下正常逻辑,没有问题

4.问题点排查
4.1 elasticjob 有misfire机制, 是单节点分片下. 前一轮任务没执行完(这个没执行完的意思是线程没结束, 如果由于job调用其他服务导致的dubbo调用超时导致任务提前结束, 这就有问题了, 最好此时要在执行任务的应用层的最外部或者直接在job调用开始前, 加上全局锁实现幂等), 后一轮任务是不会执行的.

4.2 分布式锁

RLock lock = redissonClient.getLock(lockName);
 b = lock.tryLock(0, 60 * 60, TimeUnit.SECONDS);
 finally {
 if (b) {
 lock.unlock();
 }
 }


这是创建锁和释放锁的代码.
4.2.1创建锁的时候, 有两个选择
a. 指定leaseTime, 超过一定时间就释放锁, 不管逻辑有没有执行完, 所以指定一个合理大的leaseTime是要商榷的.这个过期时间是加载redis数据结构上的, 不管服务端有什么变化, 宕机或死循环锁啥的, 超时后redis就认为这个锁失效了
短了会误释放锁(我们这个业务可能就是碰到了这个情况, 指定了一小时, 结果一小时没有执行完, 锁被释放了), 长了就影响不太好
b.不指定leaseTime, 或者leaseTime=-1, 只有此时时才会使用看门狗;看门狗默认续租时间是 10s 左右,internalLockLeaseTime / 3;可以通过 Config 统一设置看门狗的时间,设置 lockWatchdogTimeout 参数即可。看门狗的作用就是大概就是在服务端设置一个定时任务, 服务端不断的向redis发起请求, 除非这把锁被程序员手动释放掉了, 或者服务器宕机或者与redis失联, 导致看门狗定时任务无法请求到redis. 所以锁因为没有被续租就被释放
比起, 没有看门狗来, 宕机或者与redis失联下会释放锁, 但是两条看门狗的死循环锁是不会释放锁的(一般场景下, 全局锁的名字都不一样, 而且一把锁一般就用在一个位置, 不会满足循环死锁的竞态条件), 看门狗定时任务还是不断的续租… 除非有一个是强制超时释放而不是看门狗.
这个看门狗启动后对整体性能也会有一定影响,所以不建议开启看门狗。

4.2.2释放锁

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


这个代码有点问题, 也许去尝试释放别的线程持有的同名锁(redisson释放锁前会检查, 如果当前线程没有释放锁会报错, attempt to unlock lock, not locked by current thread by node id:, 由于程序员释放锁是在finally代码, 所以会直接返回异常给调用方)所以建议写成:

if (lock != null && lock.isHeldByCurrentThread()) {
 lock.unlock();
 }


我后来想想, 其实也没有问题, if (b) 我想不到什么情况下会有问题

5、Redis分布式锁的缺点 (这段是抄的)
Redis分布式锁会有个缺陷,就是在Redis哨兵模式下:

客户端1 对某个 master节点写入了redisson锁,此时会异步复制给对应的 slave节点。但是这个过程中一旦发生 master节点宕机,主备切换,slave节点从变为了 master节点。

这时 客户端2 来尝试加锁的时候,在新的master节点上也能加锁,此时就会导致多个客户端对同一个分布式锁完成了加锁。

这时系统在业务语义上一定会出现问题,导致各种脏数据的产生。

缺陷在哨兵模式或者主从模式下,如果 master实例宕机的时候,可能导致多个客户端同时完成加锁



https://www.xamrdz.com/database/6sv1928756.html

相关文章: