[分布式锁] Redisson中的看门狗机制总结

1、普通的Redis分布式锁的缺陷

我们在网上看到的redis分布式锁的工具方法,大都满足互斥、防止死锁的特性,有些工具方法会满足可重入特性。
如果只满足上述3种特性会有哪些隐患呢?redis分布式锁无法自动续期,比如,一个锁设置了1分钟超时释放,如果拿到这个锁的线程在一分钟内没有执行完毕,那么这个锁就会被其他线程拿到,可能会导致严重的线上问题,我已经在秒杀系统故障排查文章中,看到好多因为这个缺陷导致的超卖了。


2、redisson分布式锁

[分布式锁] Redisson中的看门狗机制总结_第1张图片

 Redisson 锁的加锁机制如上图所示,线程去获取锁,获取成功则执行lua脚本,保存数据到redis数据库。
如果获取失败: 一直通过while循环尝试获取锁(可自定义等待时间,超时后返回失败),获取成功后,执行lua脚本,保存数据到redis数据库。
Redisson提供的分布式锁是支持锁自动续期的,也就是说,如果线程仍旧没有执行完,那么redisson会自动给redis中的目标key延长超时时间,这在Redisson中称之为 Watch Dog 机制。
同时 redisson 还有公平锁、读写锁的实现。使用样例如下,附有方法的详细机制释义

private void redissonDoc() throws InterruptedException {    
   //1. 普通的可重入锁 拿锁失败时会不停的重试
    RLock lock = redissonClient.getLock("generalLock");   
 
    // 具有Watch Dog自动延期机制,默认续30s,每隔10s就会进行一次续期,把锁重置成30秒
    lock.lock();   

    // 没有Watch Dog ,10s后自动释放 
    lock.lock(10, TimeUnit.SECONDS);   

    // 尝试拿锁10s后停止重试,返回false
    boolean res1 = lock.tryLock(10, TimeUnit.SECONDS);   

     // 拿锁重试时间100s,租期时间10s,10s后自动释放锁,看门狗续期失效
    boolean res2 = lock.tryLock(100, 10, TimeUnit.SECONDS);  
 
    //2. 公平锁 保证 Redisson 客户端线程将以其请求的顺序获得锁
    RLock fairLock = redissonClient.getFairLock("fairLock");  
  
    //3. 读写锁 没错与JDK中ReentrantLock的读写锁效果一样
    RReadWriteLock readWriteLock = redissonClient.getReadWriteLock("readWriteLock");
    readWriteLock.readLock().lock();
    readWriteLock.writeLock().lock();
}

3、Redisson中的机制

超时时间:如果拿到分布式锁的节点宕机,且这个锁正好处于锁住的状态时,会出现锁死的状态,为了避免这种情况的发生,锁都会设置一个过期时间,分布式锁的超时时间默认是30秒。

设置超时时间:另外Redisson 还提供了可以指定leaseTime参数的加锁方法来指定加锁的时间。超过这个时间后锁便自动解开了,不会延长锁的有效期。

watch dog自动延期机制:这样也存在一个问题,如果一个线程拿到了锁设置了30s超时,在30s后这个线程还没有执行完毕,锁超时释放了,就会导致问题。Redisson提供了一个监控锁的看门狗,它的作用是在Redisson实例被关闭前,不断的延长锁的有效期,也就是说,如果一个拿到锁的线程一直没有完成逻辑,那么看门狗会帮助线程不断的延长锁超时时间,锁不会因为超时而被释放。默认情况下,看门狗每隔10s就会进行一次续期,把锁重置成30秒,也可以通过修改Config.lockWatchdogTimeout来另行指定。

尝试获取锁时间:线程会尝试在一定时间内获取锁,如果超时则表示获取失败,返回false

宕机:如果宕机了定时任务跑不了,就续不了期,那自然30秒之后锁就解开了

注意:如果程序释放锁操作时因为异常没有被执行,那么锁无法被释放,所以释放锁操作一定要放到 finally {} 中;

你可能感兴趣的:(#,Redis,redis,缓存,数据库)