前言
最近开发了几个微服务上线了,发现定时任务执行了很多次,查看rancher发现这几个微服务都是多实例的,也就是说定时任务执行了多次,恰好所用框架中使用的是Redisson, 正好记录下使用Redission实现分布式锁
正文
配置
添加Redisson依赖
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>3.6.5</version>
</dependency>
添加配置类
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class RedissonConfiguration {
@Value("${spring.redis.host}")
private String host;
@Value("${spring.redis.password}")
private String password;
@Value("${spring.redis.port:6379}")
private String port;
@Value("${spring.redis.clientName:${eureka.instance.instanceId}}")
private String clientName;
@Value("${spring.redis.idleConnectionTimeout:10000}")
private int idleConnectionTimeout;
@Value("${spring.redis.pingTimeout:1000}")
private int pingTimeout;
@Value("${spring.redis.connectTimeout:10000}")
private int connectTimeout;
@Value("${spring.redis.timeout:3000}")
private int timeout;
@Value("${spring.redis.retryAttempts:3}")
private int retryAttempts;
@Value("${spring.redis.retryInterval:1500}")
private int retryInterval;
@Value("${spring.redis.subscriptionsPerConnection:5}")
private int subscriptionsPerConnection;
@Value("${spring.redis.subscriptionConnectionMinimumIdleSize:1}")
private int subscriptionConnectionMinimumIdleSize;
@Value("${spring.redis.subscriptionConnectionPoolSize:10}")
private int subscriptionConnectionPoolSize;
@Value("${spring.redis.connectionMinimumIdleSize:32}")
private int connectionMinimumIdleSize;
@Value("${spring.redis.connectionPoolSize:64}")
private int connectionPoolSize;
@Value("${spring.redis.database:1}")
private int database;
@Value("${spring.redis.dnsMonitoring:false}")
private boolean dnsMonitoring;
@Value("${spring.redis.dnsMonitoringInterval:5000}")
private int dnsMonitoringInterval;
@Bean
public RedissonClient redisson() {
Config config = new Config();
config.useSingleServer()
.setAddress(String.format("redis://%s:%s", host,port))
.setClientName(clientName)
.setPassword(password)
.setIdleConnectionTimeout(idleConnectionTimeout)
.setPingTimeout(pingTimeout)
.setConnectTimeout(connectTimeout)
.setTimeout(timeout)
.setRetryAttempts(retryAttempts)
.setRetryInterval(retryInterval)
.setSubscriptionsPerConnection(subscriptionsPerConnection)
.setSubscriptionConnectionMinimumIdleSize(subscriptionConnectionMinimumIdleSize)
.setSubscriptionConnectionPoolSize(subscriptionConnectionPoolSize)
.setConnectionMinimumIdleSize(connectionMinimumIdleSize)
.setConnectionPoolSize(connectionPoolSize)
.setDatabase(database)
.setDnsMonitoring(dnsMonitoring)
.setDnsMonitoringInterval(dnsMonitoringInterval);
return Redisson.create(config);
}
}
使用
@Inject
RedissonClient redisson;
RLock lock;
public void method() {
try {
// key替换为锁key, 不要与其他锁key冲突
lock = redisson.getLock("key");
// 参数1为等待时间,超时return
// 参数2为锁的过期时间
// 参数3为时间单位
// 本例中,得不到锁立即失败,50秒后自动解锁
if (!lock.tryLock(0, 50, TimeUnit.SECONDS)) {
return;
}
// 业务逻辑
lock.forceUnlock();
} catch (InterruptedException e) {
// 重置线程打断状态
Thread.currentThread().interrupt();
}
}