前提介绍
后端代码框架:SpringBoot+mybatis
Redisson的优势
Redisson提供了一个监控锁的看门狗(watch dog),它的作用是在Redisson实例被关闭前,不断(默认每10s)的延长锁(redis中的目标key)的有效期(默认续期到30s),也就是说,如果一个拿到锁的线程一直没有完成逻辑,那么看门狗会帮助线程不断的延长锁的超时时间,锁不会因为超时而被释放。加锁的业务只要运行完成,就不会给当前锁续期,即使不手动解锁,锁默认会在30s内自动过期,不会产生死锁问题; 默认情况下,看门狗的续期时间是30s,也可以通过修改Config.lockWatchdogTimeout来另行指定。 另外Redisson还提供了可以指定leaseTime参数的加锁方法来指定加锁的时间。超过这个时间后锁便自动解开了,不会延长锁的有效期。
Redisson的使用
1、加依赖
<!--redisson-->
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-boot-starter</artifactId>
<version>3.13.6</version>
<exclusions>
<exclusion>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-data-23</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-data-21</artifactId>
<version>3.13.6</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
注意:关于版本,直接去官网找下最新版即可,通过redisson-spring-data-xx来适配Spring的版本。上述就是适配spring2.x版本的配置;
2、改配置
redisson-spring-boot-starter支持两种配置方式,第一种是完全兼容spring-boot-starter-data-redis的配置(redis和redisson都在application.yml中配置); 第二种是使用redisson自己的配置方式,即在application.yml中只配置redis,然后使用spring.redis.redisson.config=classpath:redisson.yml来指定redisson的配置文件名称,然后在redisson.yml中配置redisson。
方式一(
application.yml文件)
spring:
## Redis配置
redis:
password: xxxx1234
cluster:
nodes: 10.163.xx.111:6381,10.163.xx.111:6382,10.163.xx.112:6381,10.163.xx.112:6382,10.163.xx.113:6381,10.163.xx.113:6382
jedis:
pool:
#最大连接数
max-active: 8
#最大阻塞等待时间(负数表示没限制)
max-wait: -1
#最小空闲
min-idle: 0
#最大空闲
max-idle: 8
#连接超时时间
timeout: 10000
##Redisson配置
redisson:
enable: true
cluster-servers-config:
cluster-nodes: ${spring.redis.cluster.nodes}
load-balancer-mode: RADOM
password: ${spring.redis.password}
slave-connection-minimum-idle-size: 8
slave-connection-pool-size: 16
sslEnableEndpointIdentification: false
threads: 8
nettyThreads: 8
transportMode: NIO
方式二(
redisson.yml文件)
# 单节点配置
singleServerConfig:
# 连接空闲超时,单位:毫秒
idleConnectionTimeout: 10000
# 连接超时,单位:毫秒
connectTimeout: 10000
# 命令等待超时,单位:毫秒
timeout: 3000
# 命令失败重试次数,如果尝试达到 retryAttempts(命令失败重试次数) 仍然不能将命令发送至某个指定的节点时,将抛出错误。
# 如果尝试在此限制之内发送成功,则开始启用 timeout(命令等待超时) 计时。
retryAttempts: 3
# 命令重试发送时间间隔,单位:毫秒
retryInterval: 1500
# 密码
password: redis.shbeta
# 单个连接最大订阅数量
subscriptionsPerConnection: 5
# 客户端名称
clientName: axin
# # 节点地址
address: redis://redis.shbeta@m-redis-k8s.shbeta.ke.com:36479
# 发布和订阅连接的最小空闲连接数
subscriptionConnectionMinimumIdleSize: 1
# 发布和订阅连接池大小
subscriptionConnectionPoolSize: 50
# 最小空闲连接数
connectionMinimumIdleSize: 32
# 连接池大小
connectionPoolSize: 64
# 数据库编号
database: 6
# DNS监测时间间隔,单位:毫秒
dnsMonitoringInterval: 5000
# 线程池数量,默认值: 当前处理核数量 * 2
#threads: 0
# Netty线程池数量,默认值: 当前处理核数量 * 2
#nettyThreads: 0
# 编码
codec: !<org.redisson.codec.JsonJacksonCodec> {}
# 传输模式
transportMode : "NIO"
注意:配置项需要参照org.redisson.config,如果你想配置集群模式的Redisson,就点Config的成员变量ClusterServersConfig去看下里边有哪些可配置项
3、简单代码使用
package com.nariit.adf.redission;
import org.redisson.api.RLock;
import java.util.concurrent.TimeUnit;
/**
* Redisson分布式锁接口
*
* RLock的实现
* 有可重入非公平锁(RedissonLock)、可重入公平锁(RedissonFairLock)、联锁(RedissonMultiLock)、 红锁(RedissonRedLock)、
* 读锁(RedissonReadLock)、 写锁(RedissonWriteLock)等
*/
public interface DistributedLocker {
RLock lock(String lockKey);
RLock lock(String lockKey, long timeout);
RLock lock(String lockKey, TimeUnit unit, long timeout);
boolean tryLock(String lockKey, TimeUnit unit, long leaseTime);
boolean tryLock(String lockKey, TimeUnit unit, long waitTime, long leaseTime);
void unlock(String lockKey);
void unlock(RLock lock);
}
package com.nariit.adf.redission;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.concurrent.TimeUnit;
/**
* Redisson分布式锁实现-使用可重入非公平锁(RedissonLock)
* leaseTime 锁的持续时间
* waitTime 获取锁的等待时间
*/
@Component
public class RedissonDistributedLocker implements DistributedLocker {
@Autowired
private RedissonClient redissonClient;
@Override
public RLock lock(String lockKey) {
RLock lock = this.redissonClient.getLock(lockKey);
lock.lock();
return lock;
}
@Override
public RLock lock(String lockKey, long timeout) {
RLock lock = this.redissonClient.getLock(lockKey);
//支持过期解锁功能,10秒钟以后自动解锁, 无需调用unlock方法手动解锁
lock.lock(timeout, TimeUnit.SECONDS);
return lock;
}
@Override
public RLock lock(String lockKey, TimeUnit unit, long timeout) {
RLock lock = this.redissonClient.getLock(lockKey);
lock.lock(timeout, unit);
return lock;
}
@Override
public boolean tryLock(String lockKey, TimeUnit unit, long leaseTime) {
RLock lock = this.redissonClient.getLock(lockKey);
try {
return lock.tryLock(0L, leaseTime, unit);
}catch (InterruptedException var7){
return false;
}
}
@Override
public boolean tryLock(String lockKey, TimeUnit unit, long waitTime, long leaseTime) {
RLock lock = redissonClient.getLock(lockKey);
try {
return lock.tryLock(waitTime, leaseTime, unit);
}catch (InterruptedException var7){
return false;
}
}
@Override
public void unlock(String lockKey) {
RLock lock = redissonClient.getLock(lockKey);
try {
if(lock.isLocked()){
lock.unlock();
}
}catch (IllegalMonitorStateException var7){}
}
@Override
public void unlock(RLock lock) {
try {
if (lock.isLocked()) {
lock.unlock();
}
} catch (IllegalMonitorStateException var3) {}
}
}
如图片所示: