Redis-习-02-Redis分布式锁(Redisson)

本文介绍如何使用 Redisson 框架在 SpringBoot 项目中实现分布式锁,包括添加 Maven 依赖、配置 RedissonClient 和使用锁的示例代码。针对单节点、集群、哨兵和云服务的不同配置进行了讲解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Redis-习-02-Redis分布式锁(Redisson)

自己写的基于Redis+Lua脚本的分布式锁,经测试存在一些Redis连接池方面的问题,同时存在多节点Redis情况下的使用不严谨,故采用官方推荐的Redisson框架来实现。

  1. Redisson官方文档
  2. 项目使用框架为SpringBoot,Redisson提供了整合SpringBoot的jar包,在这里并没有使用,因为如果使用了这个整合包,就会整体替换掉项目中Redis的客户端类型。项目中之前使用的是Spring自带的RedisTemplate,也就是Jedis客户端。

1. 添加maven依赖

  1. 这是独立的Redisson的maven依赖包,而不是Redisson-SpringBoot整合包
<dependency>
    <groupId>org.redisson</groupId>
    <artifactId>redisson</artifactId>
    <version>3.10.1</version>
</dependency>
  1. 这是Redisson官方提供的整合SpringBoot的包(我没有用这种方式)
<dependency>
	<groupId>org.redisson</groupId>
	<artifactId>redisson-spring-data-16</artifactId>
	<version>3.11.3</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.redisson/redisson-spring-boot-starter -->
<dependency>
	<groupId>org.redisson</groupId>
	<artifactId>redisson-spring-boot-starter</artifactId>
	<version>3.11.3</version>
</dependency>

2. 编写配置RedissonClient的配置类

Redisson官方文档,官方文档中对配置有非常详细的说明,对于Redis是单节点、集群、哨兵、云服务厂商等都有不同的配置方式

  1. 编写配置类,实例化RedissonClient。我这里用的读取yml配置文件的方式,官方还有读取json文件方式或者代码中配置
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.redisson.config.TransportMode;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.io.IOException;

@Configuration
public class RedissonConfig {
    @Bean
    public RedissonClient redissonClient() throws IOException {
        // 本例子使用的是yaml格式的配置文件,读取使用Config.fromYAML,如果是Json文件,则使用Config.fromJSON
        Config config = Config.fromYAML(RedissonConfig.class.getClassLoader().getResource("redisson.yml"));
        return Redisson.create(config);
    }
}

  1. 编写 redisson.yml(放在项目的resource目录下)。Redis单节点、集群、哨兵模式的配置内容不一样,具体看官方文档。我这里用的是哨兵模式配置,是复制的官方提供的模板
sentinelServersConfig:
    idleConnectionTimeout: 10000
    pingTimeout: 1000
    connectTimeout: 10000
    timeout: 3000
    retryAttempts: 3
    retryInterval: 1500
    reconnectionTimeout: 3000
    failedAttempts: 3
    password: null
    subscriptionsPerConnection: 5
    clientName: null
    loadBalancer: !<org.redisson.connection.balancer.RoundRobinLoadBalancer> {}
    slaveSubscriptionConnectionMinimumIdleSize: 1
    slaveSubscriptionConnectionPoolSize: 50
    slaveConnectionMinimumIdleSize: 32
    slaveConnectionPoolSize: 64
    masterConnectionMinimumIdleSize: 32
    masterConnectionPoolSize: 64
    readMode: "SLAVE"
    sentinelAddresses:
        - "redis://127.0.0.1:26400"
        - "redis://127.0.0.1:26401"
        - "redis://127.0.0.1:26402"
    masterName: "mymaster"
    database: 0
threads: 0
nettyThreads: 0
codec: !<org.redisson.codec.JsonJacksonCodec> {}
transportMode: "NIO"
  1. 这是代码配置的举例,里面共写了三种,只需要其中一种即可(个人不喜欢这种方式,毕竟是写死在代码中,还是使用配置文件的方式好,因为以后有模式的修改等等都只要改配置文件,不用修改代码)
    @Bean
    public RedissonClient redissonClient() {
        Config config = new Config();
        // 哨兵模式
        config.useSentinelServers()
                .setMasterName("mymaster")
                .addSentinelAddress("redis://127.0.0.1:26400","redis://127.0.0.1:26401","redis://127.0.0.1:26402");
        // 单节点模式
        config.setTransportMode(TransportMode.NIO);
        config.useSingleServer().setAddress("redis://127.0.0.1:6400");
        // cluster 集群模式
        config.useClusterServers()
                .setScanInterval(2000)
                .addNodeAddress("redis://127.0.0.1:7001", "redis://127.0.0.1:7002")
                .addNodeAddress("redis://127.0.0.1:7003", "redis://127.0.0.1:7004")
                .addNodeAddress("redis://127.0.0.1:7005", "redis://127.0.0.1:7006");*//*
        return Redisson.create(config);
    }

3. 代码中使用 RedissonClient Bean实例

  1. Redisson官方文档,这里面有使用锁的详细用法
  2. 我这里简单举例使用
    @Autowired
    private RedissonClient redissonClient;
    
    @RequestMapping("/testLock")
    public R testLock(){
        RLock lock = redissonClient.getLock("testLock");
        boolean tryLock = false;
        try {
            // 第一个参数是获取锁最长等待时间(超时时间),第二个是锁的有效时间(缓存到Redis时间),第三个为时间类型
            // 示例:获取锁最长等待3秒,3秒内没获取到,tryLick 为 false。缓存设置为2秒
            tryLock = lock.tryLock(3, 2, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            if (tryLock) {
                lock.unlock();
            }
        }
        return R.ok();
    }
  1. 红锁 RedLock 使用
    参考

关于 Redis 官方推荐的 RedLock 算法使用,这里有点模糊的是关于节点的数量问题。比如我本地用的一套哨兵集群,内有三个Redis节点,一主两从。事实上这个在 RedLock 中只算作一个节点。RedLock中节点的意思是相互独立的,不存在数据共享或者复制情况。如三套哨兵集群,三套Cluster集群。三个独立节点

参考说明:核心的变化就是需要构建多个 RLock ,然后根据多个 RLock 构建成一个 RedissonRedLock,因为 redLock 算法是建立在多个互相独立的 Redis 环境之上的(为了区分可以叫为 Redission node),Redission node 节点既可以是单机模式(single),也可以是主从模式(master/salve),哨兵模式(sentinal),或者集群模式(cluster)。这就意味着,不能跟以往这样只搭建 1个 cluster、或 1个 sentinel 集群,或是1套主从架构就了事了,需要为 RedissonRedLock 额外搭建多几套独立的 Redission 节点。 比如可以搭建3个 或者5个 Redission节点,具体可看视资源及业务情况而定。

    @RequestMapping("/redLock")
    public R redLock() throws InterruptedException {
        RLock lock1 = redissonClient.getLock("redLock");
        RLock lock2 = redissonClient.getLock("redLock");
        RLock lock3 = redissonClient.getLock("redLock");
        RedissonRedLock redLock = new RedissonRedLock(lock1, lock2, lock3);
        boolean flag = false;
        try {
            // 第一个参数是获取锁最长等待时间(超时时间),第二个是锁的有效时间(缓存到Redis时间),第三个为时间类型
            // 示例:获取锁最长等待3秒,3秒内没获取到,tryLick 为 false。缓存设置为2秒
            // 同时加锁:lock1 lock2 lock3
            // 红锁在大部分节点上加锁成功就算成功。
            flag = redLock.tryLock(3, 2, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            if (flag) {
                redLock.unlock();
            }
        }
        return R.ok().put("data", flag);
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值