前段时间在kubernetes中做多副本部署时,发现有些服务中存在定时任务,这样一来不同副本都会执行这些定时任务,导致任务重复执行,然后找了一下决定使用 Redisson 来做这个,其实现在来看分布式时锁相对容易多了,就是在同一时刻去获取一把锁,拿到这把锁就可以进行操作,拿不到就不能操作,这里 Redisson 是利用在 Redis 存放一个 Key (其实是setNX)来做这个工作。当然定时任务仅仅分布式锁运用的一种场景。现在 Redisson 的使用也简单了很多,官方直接提供了 redisson-spring-boot-starter,和SpringBoot整合也很方便,下面是集成示例:

1. 引入依赖
注:redisson-spring-data 需要根据项目中使用的 SpringBoot 的版本进行重选,3.11.5 版本默认引用的是 redisson-spring-data-21(即适用于SpringBoot版本为2.1.x的使用),但项目中我的SpringBoot是2.0.7就不行,需要选用redisson-spring-data-20,不做这一步启动会出错的,具体的pom依赖为:

<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-data-20</artifactId>
<version>3.11.5</version>
</dependency>

<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-boot-starter</artifactId>
<version>3.11.5</version>
<exclusions>
<exclusion>
<artifactId>redisson-spring-data-21</artifactId>
<groupId>org.redisson</groupId>
</exclusion>
</exclusions>
</dependency>
 
2. 配置
 配置方面如果只想试试,直接在application.properties文件中使用Spring-data-redis的基本配置即可:

spring.redis.database=
spring.redis.host=
spring.redis.port=
spring.redis.password=
 
当然更全面的配置可以通过spring.redis.redisson.config=classpath:redisson.yaml的方式以外部配置的方式植入,示例文件如下:

 

## 1. 云托管方式(注意名字)
#replicatedServersConfig:
# # 连接空闲超时,默认值10000,如果当前连接池里的连接数量超过了最小空闲连接数,同时有连接空闲时间超过了该数值,那这些连接将会自动被关闭,并从连接池里去掉
# idleConnectionTimeout: 10000
# pingTimeout: 1000
# # 连接超时,默认10000,同任何节点建立连接时的等待超时
# connectTimeout: 10000
# # 命令等待超时
# timeout: 3000
# # 命令失败重试次数,如果命令尝试次数超过该值仍然不能发送至某个指定的节点时,将抛出错误。如果尝试在此限制之内发送成功,则开始启用 timeout(命令等待超时) 计时
# retryAttempts: 3
# # 命令重试发送时间间隔
# retryInterval: 1500
# # 当与某个节点的连接断开时,等待与其重新建立连接的时间间隔
# reconnectionTimeout: 3000
# # 执行失败最大次数,在某个节点执行相同或不同命令时,连续失败次数大于该数值时,该节点将被从可用节点列表里清除,直到 reconnectionTimeout 超时以后再次尝试
# failedAttempts: 3
# password: 123456
# # 单个连接最大订阅数量
# subscriptionsPerConnection: 5
# # 客户端名称,在Redis节点里显示的客户端名称
# clientName: null
# # 负载均衡算法类的选择,多Redis服务节点的环境里有3种可选:
# # org.redisson.connection.balancer.WeightedRoundRobinBalancer - 权重轮询调度算法
# # org.redisson.connection.balancer.RoundRobinLoadBalancer - 轮询调度算法(默认)
# # org.redisson.connection.balancer.RandomLoadBalancer - 随机调度算法
# loadBalancer: org.redisson.connection.balancer.RoundRobinLoadBalancer
# # slave用于发布和订阅连接的最小保持连接数(长连接),默认值1。Redisson内部经常通过发布和订阅来实现许多功能。长期保持一定数量的发布订阅连接是必须的
# slaveSubscriptionConnectionMinimumIdleSize: 1
# # slave的发布和订阅连接池大小,默认50,连接池的连接数量自动弹性伸缩
# slaveSubscriptionConnectionPoolSize: 50
# # slave的最小空闲连接数
# slaveConnectionMinimumIdleSize: 32
# # slave的连接池大小,默认64,连接池的连接数量自动弹性伸缩
# slaveConnectionPoolSize: 64
# # mater的最小空闲连接数
# masterConnectionMinimumIdleSize: 32
# # mater的连接池大小
# masterConnectionPoolSize: 64
# # 读取操作的负载均衡模式:SLAVE-只在从服务节点里读取,MASTER-只在主服务节点里读取,MASTER_SLAVE-在主、从服务节点里都可以读取
# readMode: "SLAVE"
# # 节点地址,通过host:port的格式来指定云托管模式的多个Redis集群节点的地址
# nodeAddresses:
# - "redis://127.0.0.1:6379"
# - "redis://127.0.0.1:6380"
# # 主节点变化扫描间隔时间,对主节点变化节点状态扫描的时间间隔
# scanInterval: 1000
## 线程池数量,默认=当前处理核数量*2,该线程池数量被所有RTopic对象监听器,RRemoteService调用者和RExecutorService任务共同共享
#threads: 0
## Netty线程池数量,默认=当前处理核数量*2,该线程池数量是在一个Redisson实例内,被其创建的所有分布式数据类型和服务,以及底层客户端所一同共享的线程池里保存的线程数量
#nettyThreads: 0
## 编码,Redisson的对象编码类是用于将对象进行序列化和反序列化,以实现对该对象在Redis里的读取和存储,默认JsonJacksonCodec
#codec: org.redisson.codec.JsonJacksonCodec
## 传输模式,可选:NIO(默认)、EPOLL(需要依赖里有netty-transport-native-epoll包 Linux)、KQUEUE(需要依赖里有 netty-transport-native-kqueue包(macOS)
#transportMode:"NIO"

# 1. 单节点
singleServerConfig:
idleConnectionTimeout: 10000
pingTimeout: 1000
connectTimeout: 10000
timeout: 3000
retryAttempts: 3
retryInterval: 1500
reconnectionTimeout: 3000
failedAttempts: 3
password: null
subscriptionsPerConnection: 5
clientName: null
address: "redis://192.168.1.7:6379"
subscriptionConnectionMinimumIdleSize: 1
subscriptionConnectionPoolSize: 50
connectionMinimumIdleSize: 32
connectionPoolSize: 64
database: 0
# dnsMonitoring: false
# dnsMonitoringInterval: 5000
threads: 0
nettyThreads: 0
codec: !<org.redisson.codec.JsonJacksonCodec> {}
transportMode: NIO

# 2. 主从节点
#masterSlaveServersConfig:
# idleConnectionTimeout: 10000
# pingTimeout: 1000
# connectTimeout: 10000
# timeout: 3000
# retryAttempts: 3
# retryInterval: 1500
# reconnectionTimeout: 3000
# failedAttempts: 3
# password: 123456
# subscriptionsPerConnection: 5
# clientName: null
# loadBalancer: !<org.redisson.connection.balancer.RoundRobinLoadBalancer> {}
# slaveSubscriptionConnectionMinimumIdleSize: 1
# slaveSubscriptionConnectionPoolSize: 50
# slaveConnectionMinimumIdleSize: 32
# slaveConnectionPoolSize: 64
# masterConnectionMinimumIdleSize: 32
# masterConnectionPoolSize: 64
# readMode: "SLAVE"
# slaveAddresses:
# - "redis://127.0.0.1:6380"
# masterAddress: "redis://127.0.0.1:6379"
# database: 0
#threads: 0
#nettyThreads: 0
#codec: !<org.redisson.codec.JsonJacksonCodec> {}
#"transportMode": "NIO"

3. 使用
 在使用redisson客户端时,就不需要再去配置jedis或者lettuce相关参数了,同样具备RedisTemplate可以使用

@Autowired
RedisTemplate<String, Object> redisTemplate;
@Autowired
RedissonClient redissonClient;

public void testRedisson() {
// 获取可重入锁
RLock rLock = redissonClient.getLock(“test-lock”);
try {
// 如果该线程无法获取锁将会不断尝试,但至多2s,如果仍未获取,返回false
// 如果该线程获取锁了,这个锁将会在redis中存活60s,返回true
boolean lock = rLock.tryLock(2, 60, TimeUnit.SECONDS);
if (lock) {
System.out.println(“get lock success!”);
}
} catch (InterruptedException e) {
e.printStackTrace();
}

// 利用体用的模板对redis进行操作
redisTemplate.opsForValue().set(“test2”, buildProject());
}

private Project buildProject() {
Project project = new Project();
project.setId(1);
project.setName(“测试”);
project.setUserId(111);
project.setCreateTime(new Date());
return project;
}
 
Redisson 存入的锁对应的value是一个UUID:线程ID的形式,具体可到redis中自行查看。

————————————————
版权声明:本文为CSDN博主「jacksonary」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/jacksonary/article/details/103586564