分布式 | Redisson实现分布式锁

实现分布式锁-Redisson

1、概述

  • Redisson 是一个在Redis的基础上实现的Java驻内存数据网格(In-Memory Data Grid)。它不仅提供了一系列的分布式的Java常用对象,还提供了许多分布式服务。
  • Redisson 的宗旨是:促进使用者对Redis的关注分离(Separation of Concern),从而让使用者能够将精力更集中地放在处理业务逻辑上。

2、四个条件

为了确保分布式锁可用,我们至少要确保锁的实现同时满足以下四个条件:

  • 第一个:互斥性,在任何时刻,只有一个客户端能持有锁。
  • 第二个:不会发生死锁,即使有一个客户端在获取锁操作时候崩溃了,也能保证其他客户端能获取到锁。
  • 第三个:解铃还须系铃人,解锁加锁必须同一个客户端操作。
  • 第四个:加锁和解锁必须具备原子性

3、引入依赖

<dependency>
    <groupId>org.redisson</groupId>
    <artifactId>redisson</artifactId>
</dependency>

4、配置类别

创建RedissonConfig 配置类
@Data
@Configuration
@ConfigurationProperties(prefix = "spring.data.redis")
public class RedissonConfig {

    private String host;

    private String password;

    private String port;

    private int timeout = 3000;
    private static String ADDRESS_PREFIX = "redis://";

    /**
     * 自动装配
     *
     */
    @Bean
    RedissonClient redissonSingle() {
        Config config = new Config();

        if(!StringUtils.hasText(host)){
            throw new RuntimeException("host is  empty");
        }
        SingleServerConfig serverConfig = config.useSingleServer()
                .setAddress(ADDRESS_PREFIX + this.host + ":" + port)
                .setTimeout(this.timeout);
        if(StringUtils.hasText(this.password)) {
            serverConfig.setPassword(this.password);
        }
        return Redisson.create(config);
    }
}

配置 application.yml

spring:
    data:
        redis:
          host: 192.168.2.5
          port: 6379
          database: 0
          timeout: 1800000
          password:
          jedis:
            pool:
              max-active: 20 #最大连接数
              max-wait: -1    #最大阻塞等待时间(负数表示没限制)
              max-idle: 5    #最大空闲
              min-idle: 0 

5、代码实现

 public void testLockRedisson() {
        // 1.获取锁 可重入锁
        RLock lock = redissonClient.getLock("lock1");
        // 2.加锁
        try {
            // 阻塞 默认过期30s  看门狗:自动续期
            lock.lock();
            // 设置过期 10s
            //lock.lock(10, TimeUnit.SECONDS);
            // 等待时间 、 设置过期时间
            // lock.tryLock(30, 10, TimeUnit.SECONDS);
            // 3.业务代码
            String value = redisTemplate.opsForValue().get("num");
            if (StringUtil.isBlank(value)) {
                return;
            }
            int num = Integer.parseInt(value);
            redisTemplate.opsForValue().set("num", String.valueOf(++num));
        } finally {
            //4.释放锁
            lock.unlock();
        }

    }

6、Redisson 看门狗

​ 基于RedisRedisson分布式可重入锁RLock Java对象实现了java.util.concurrent.locks.Lock接口。
​ 如果负责储存这个分布式锁的Redisson节点宕机以后,而且这个锁正好处于锁住的状态时,这个锁会出现锁死的状态。为了避免这种情况的发生,Redisson内部提供了一个监控锁的看门狗,它的作用是在Redisson实例被关闭前,不断的延长锁的有效期。默认情况下,看门狗的检查锁的超时时间是30秒钟,也可以通过修改Config.lockWatchdogTimeout来另行指定。

另外Redisson还通过加锁的方法提供了leaseTime的参数来指定加锁的时间。超过这个时间后锁便自动解开了。

看门狗原理:

​ 只要线程一加锁成功,就会启动一个watch dog看门狗,它是一个后台线程,会每隔10秒检查一下,如果线程还持有锁,那么就会不断的延长锁key的生存时间。因此,Redisson就是使用watch dog解决了锁过期释放,业务没执行完问题

  • 如果我们指定了锁的超时时间,就发送给Redis执行脚本,进行占锁,默认超时就是我们制定的时间,不会自动续期;
  • 如果我们未指定锁的超时时间,就使用 lockwatchdogTimeout= 30 * 1000【看门狗默认时间】
posted @ 2024-11-26 10:44  码农stormling  阅读(95)  评论(0)    收藏  举报  来源