ICode9

精准搜索请尝试: 精确搜索
首页 > 数据库> 文章详细

redis 基于 redisson 的分布式锁

2021-09-09 11:30:09  阅读:250  来源: 互联网

标签:redisson lock redissonProperties 30s redis Dog private 分布式


以前在开发项目的时候,一般使用自己基于 lua 脚本实现的 redis 锁,最近对分布式所深入了解了一下,才发现这样实现是有很大的问题的,比如说,如果线程执行时间过长,在锁释放之后还没有执行完成怎么办呢

最近又发现了一个比较好的 redis 的框架 redisson 这里面实现了 Watch Dog 自动延期功能,在这里记录一下,以便以后查阅

一、添加 redisson 配置

引入依赖:

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

添加配置(这里我就直接复制我的配置了):

@Configuration
@ConfigurationProperties(prefix = "redisson")
public class RedissonProperties {

    // 是否启动集群模式
    public boolean clusterEnabled = false;

    // redis 服务器地址,多个以逗号分割
    private String address;

    // 使用的redis数据库编号
    private int database = 0;

    // redis 登录密码
    private String password;

    // 服务器响应超时时间
    private int timeout = 3000;

    // redis 集群扫描间隔
    private int scanInterval = 1000;

    // redis连接池大小,若为集群,则为主节点连接池大小
    private int connectionPoolSize = 64;

    // 每个从节点连接连接池大小
    private int slaveConnectionPoolSize = 250;

    // redis 最小空闲连接
    private int connectionMinimumIdleSize = 10;

    // ... get and set
}

@Bean
public RedissonClient redissonClient(RedissonProperties redissonProperties) {
    Config config = new Config();
    if(redissonProperties.clusterEnabled) {
        ClusterServersConfig serverConfig = config.useClusterServers()
                .addNodeAddress(redissonProperties.getAddress().split(","))
                .setTimeout(redissonProperties.getTimeout())
                .setScanInterval(redissonProperties.getScanInterval())
                .setMasterConnectionPoolSize(redissonProperties.getConnectionPoolSize())
                .setSlaveConnectionPoolSize(redissonProperties.getSlaveConnectionPoolSize())
                .setMasterConnectionMinimumIdleSize(redissonProperties.getConnectionMinimumIdleSize())
                .setSlaveConnectionMinimumIdleSize(redissonProperties.getConnectionMinimumIdleSize());
        if(!StringUtils.isEmpty(redissonProperties.getPassword())) {
            serverConfig.setPassword(redissonProperties.getPassword());
        }
    } else {
        SingleServerConfig serverConfig = config.useSingleServer()
                .setAddress(redissonProperties.getAddress())
                .setDatabase(redissonProperties.getDatabase())
                .setTimeout(redissonProperties.getTimeout())
                .setConnectionPoolSize(redissonProperties.getConnectionPoolSize())
                .setConnectionMinimumIdleSize(redissonProperties.getConnectionMinimumIdleSize());
        if(!StringUtils.isEmpty(redissonProperties.getPassword())) {
            serverConfig.setPassword(redissonProperties.getPassword());
        }
    }
    config.setCodec(new JsonJacksonCodec());
    return Redisson.create(config);
}

二、相关锁方法介绍

1. 获取Lock实例

// 非公平锁,无法实现线程顺序获取锁
RLock lock = redissonClient.getLock("lock-key");

// 公平锁,实现线程顺序获取锁
RLock lock = redissonClient.getFairLock("lock-key");

// 红锁,获取多个关联锁的红锁实例
RLock lock = redissonClient.getRedLock();

// 多锁,获取多个关联锁的实例
RLock lock = redissonClient.getMultiLock();

// 读写锁,不做讲解
ReadWriteLock readWriteLock = redissonClient.getReadWriteLock("");

2. RLock方法详解

// 具有Watch Dog自动延期机制; 锁默认存在时间为30s;每隔30/3=10s自动续期到30s
// 尝试获取锁,获取失败时,会不停的重试;直至拿到锁
lock.lock();

// 没有Watch Dog自动延期机制;在租赁到期后,释放锁
// 尝试获取锁,获取失败时,会不停的重试;直至拿到锁
lock.lock(120000, TimeUnit.SECONDS);

// 具有Watch Dog自动延期机制; 锁默认存在时间为30s;每隔30/3=10s自动续期到30s
// 获取锁失败时,会等待,直至达到最大等待时间,返回false
boolean bool = lock.tryLock(5, TimeUnit.SECONDS);

// 没有Watch Dog自动延期机制;在租赁到期后,释放锁
// 获取锁失败时,会等待,直至达到最大等待时间,返回false
boolean bool = lock.tryLock(5, 60, TimeUnit.SECONDS);

3. Wath Dog 自动延期机制

加入一个线程拿到了锁,设置30s超时,但是在30s后这个线程还没有执行完毕,锁释放了;这就会导致问题;RedissonWatch Dog 自动延期机制,正好可以解决这个问题。

Redisson 提供了一个监控锁的 看门狗(Wath Dog);做事在 Redisson 实例被关闭前,不断延长锁的有效期;也就是说,一个线程拿到锁,一直没有执行完逻辑,那么 看门狗 会不断延长锁超时时间。

默认情况下,看门狗 续期超时时间是30s,我们可以通过 Config.lockWatchdogTimeout 来设置这个时间,另外 Redisson 加锁时,也提供了 leaseTime 参数设置锁租赁时间。超过这个时间,锁就会自动解开,不会触发延期。

标签:redisson,lock,redissonProperties,30s,redis,Dog,private,分布式
来源: https://blog.csdn.net/qq_35530330/article/details/120196805

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有