首页 > 数据库 >Redisson的锁重试和看门狗机制

Redisson的锁重试和看门狗机制

时间:2023-02-15 00:12:39浏览次数:31  
标签:Redisson long 看门狗 重试 获取 RedissonLock threadId null

先看一下自己利用setnx写的简易分布式锁,有四个问题,

1,不可重入

2,不可重试

3,超时自动释放(如果业务阻塞了,就算代码没执行完也会释放锁)

4,集群模式下怎么办?

    @Override
    public boolean tryLock(long timeoutSec) {
        // 获取线程标示
        String threadId = ID_PREFIX + Thread.currentThread().getId();
        // 获取锁
        Boolean success = stringRedisTemplate.opsForValue()
                .setIfAbsent(KEY_PREFIX + name, threadId, timeoutSec, TimeUnit.SECONDS);
        return Boolean.TRUE.equals(success);
    }

Redisson都能解决!!

锁重入:

利用hash结构记录线程id和重入次数。

 

锁重试:

redisson在尝试获取锁的时候,如果传了时间参数,就不会在获取锁失败时立即返回失败,而是会进行重试。

三个参数:最大重试时间,锁释放时间(默认为-1,会触发看门狗机制),时间单位

 

上部分源码

public boolean tryLock(long waitTime, long leaseTime, TimeUnit unit) throws InterruptedException {
        long time = unit.toMillis(waitTime);
        long current = System.currentTimeMillis();
        long threadId = Thread.currentThread().getId();
     //尝试获取锁,返回的ttl为null,表示获取成功, Long ttl = this.tryAcquire(waitTime, leaseTime, unit, threadId);
     //获取成功 if (ttl == null) { return true;
     //获取失败 } else {
       //计算剩余时间 time -= System.currentTimeMillis() - current;
        //剩余时间小于等于零,不再重试,返回失败 if (time <= 0L) { this.acquireFailed(waitTime, unit, threadId); return false; } else {
          //剩余时间大于零,subscribe订阅拿到锁的线程,该线程释放锁后会发布通知,其余等待的线程可以继续争抢。 current = System.currentTimeMillis(); RFuture<RedissonLockEntry> subscribeFuture = this.subscribe(threadId);

 

看门狗机制:

在获取锁成功以后,开启一个定时任务,每隔一段时间就会去重置锁的超时时间,以确保锁是在程序执行完unlock手动释放的,不会发生因为业务阻塞,key超时而自动释放的情况。

下面源码

private void renewExpiration() {
        RedissonLock.ExpirationEntry ee = (RedissonLock.ExpirationEntry)EXPIRATION_RENEWAL_MAP.get(this.getEntryName());
        if (ee != null) {
       //Timeout定时任务,或者叫周期任务 Timeout task = this.commandExecutor.getConnectionManager().newTimeout(new TimerTask() { public void run(Timeout timeout) throws Exception { RedissonLock.ExpirationEntry ent = (RedissonLock.ExpirationEntry)RedissonLock.EXPIRATION_RENEWAL_MAP.get(RedissonLock.this.getEntryName()); if (ent != null) { Long threadId = ent.getFirstThreadId(); if (threadId != null) { RFuture<Boolean> future = RedissonLock.this.renewExpirationAsync(threadId); future.onComplete((res, e) -> { if (e != null) { RedissonLock.log.error("Can't update lock " + RedissonLock.this.getName() + " expiration", e); } else { if (res) { RedissonLock.this.renewExpiration(); } } }); } } }
        //刷新周期, this.internalLockLeaseTime / 3L, 默认释放时间是30秒,除以3就是每10秒更新一次
}, this.internalLockLeaseTime / 3L, TimeUnit.MILLISECONDS); ee.setTimeout(task); } }

 

可以配合下面流程图来看源码

 

 

 

集群问题:

实际生产过程中,redis都是主从或者集群配置的,如果只在主节点上加锁,之后主节点宕机了,而且锁还没被同步到从节点上,就会出现安全问题。

需要使用multilock()方法。必须在所有的节点都获取锁成功,才算成功。 缺点是运维成本高,实现复杂。

    @Resource
    private RedissonClient redissonClient;
    @Resource
    private RedissonClient2 redissonClient2;
    @Resource
    private RedissonClient3 redissonClient3;

    RLock lock = redissonClient.getMultilock(lock1,lock2,lock3)

 

标签:Redisson,long,看门狗,重试,获取,RedissonLock,threadId,null
From: https://www.cnblogs.com/tyleaf/p/17121281.html

相关文章

  • 详解Redisson分布式限流的实现原理
    摘要:本文将详细介绍下RRateLimiter的具体使用方式、实现原理还有一些注意事项。本文分享自华为云社区《详解Redisson分布式限流的实现原理》,作者:xindoo。我们目前在工作......
  • RPC异常重试机制详解
    1异常重试的意义发起一次RPC调用,调用远程的一个服务,如用户的登录操作,先对用户的用户名以及密码进行验证,验证成功后,获取用户基本信息。通过远程的用户服务获取用户基本信息......
  • 消息重试框架 Spring-Retry 和 Guava-Retry
    消息重试框架Spring-Retry和Guava-Retry一重试框架之Spring-RetrySpringRetry为Spring应用程序提供了声明性重试支持。它主要是针对可能抛出异常的一些调用操作,......
  • 关于看门狗的那些事
    一、SP706S看门狗SP706S看门狗,只要1.6S内给看门狗芯片高低电平信号看门狗的复位引脚就会保持高电平,如果没喂狗则为低。SP706S看门狗芯片特性,只有GPIO口为3.3V或0......
  • redisson分布式锁的应用——秒杀、超卖 简单例子(分布式锁相关)
    1、常见的分布式事务锁1、数据库级别的锁乐观锁,给予加入版本号实现悲观锁,基于数据库的forupdate实现2、Redis,基于SETNX、EXPIRE实现3、Zookeeper,基于InterProcess......
  • 75、缓存---分布式锁---Redisson信号量测试
    可以用来做分布式限流操作。我们在redis中存储一个数据为3@AutowiredRedissonClientredissonClient;@AutowiredStringRedisTemplateredisTemplate......
  • 74、缓存---分布式锁---Redisson闭锁测试
    @AutowiredRedissonClientredissonClient;@AutowiredStringRedisTemplateredisTemplate;//闭锁@GetMapping("/lockDoor")@Response......
  • 73、缓存---分布式锁---Redisson读写锁测试
    保证一定读到最新数据,修改期间,写锁是一个排他锁/互斥锁。读锁是一个共享锁。(相当于操作系统中的读写者问题)写锁没释放读必须等待测试如下:@AutowiredRedissonClient......
  • 72、缓存---分布式锁---Redisson的Lock锁测试
    @GetMapping("/hello")@ResponseBodypublicStringhello(){//1、获取一把锁,只要是锁的名字一样,就是同一把锁RLocklock=redissonClien......
  • redisson分布式锁源码和原理浅析
    在redisson之前,很多人可能已经自己实现过基于redis的分布式锁,本身原理也比较简单,redis自身就是一个单线程处理器,具备互斥的特性,通过setNx,exist等命令就可以完成简单的分布式......