说明
springboot集群部署时,定时任务存在多份,所以需要一个分布式锁来进行竞争,在zookeeper和redis之间选择,最后公司大佬磊哥说redis有个分布式锁的轮子redission,然后就去了解然后用了。单机redis和集群redis都可以使用
maven依赖
<!-- https://mvnrepository.com/artifact/org.redisson/redisson -->
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>3.13.6</version>
</dependency>
Redisson配置
yml配置
redisson:
#地址
address: "xx.xx.xx.xxx:8000,xx.xx.xx.xxx:8001,xx.xx.xx.xxx:8002"
#尝试时间
try-time: 0
#锁的时间
lock-time: 4
#redis密码
password:
#扫描间隔
scanInterval: 2000
#命令失败重试次数
retryAttempts: 5
#超时时间
timeout: 10000
client配置
@Configuration
public class RedissonConfig {
@Value(value = "${spring.redisson.address}")
private String redissonAddress;
@Value(value = "${spring.redisson.password}")
private String redissonPassword;
@Value(value = "${spring.redisson.scanInterval}")
private int redissonScanInterval;
@Value(value = "${spring.redisson.retryAttempts}")
private int redissonRetryAttempts;
@Value(value = "${spring.redisson.timeout}")
private int redissonTimeout;
@Bean
public RedissonClient getRedisClient() {
String[] nodes = redissonAddress.split(",");
for (int i = 0; i < nodes.length; i++) {
nodes[i] = "redis://" + nodes[i];
}
Config config = new Config();
config.useClusterServers() //这是用的集群server
.setScanInterval(redissonScanInterval) //设置集群状态扫描时间
.addNodeAddress(nodes).setRetryAttempts(redissonRetryAttempts).setTimeout(redissonTimeout);
if (StringUtils.isNotEmpty(redissonPassword)) {
config.useClusterServers().setPassword(redissonPassword);
}
return Redisson.create(config);
}
}
使用
{
// log.info("一次最多推送{}条数据", baseProperties.getPushDataNumber());
//先判断是否有权限推送
RLock taskLock = redissonClient.getLock(baseProperties.getPushDataLockName());
// 支持过期解锁功能,10秒钟以后自动解锁, 无需调用unlock方法手动解锁 lock.lock(10, TimeUnit.SECONDS);
// 尝试加锁,最多等待0秒,上锁以后4秒自动解锁
try {
boolean isLock = taskLock.tryLock(baseProperties.getRedssionTryTime(), baseProperties.getRedssionLockTime(), TimeUnit.SECONDS);
// 判断是否获取锁
if (!isLock) {
// 获取失败
// log.info("获取锁失败,不执行定时任务");
return;
}
try {
// log.info("获取锁成功,执行定时任务。");
// 执行任务
pushDataTaskExec();
} finally {
// 释放锁
taskLock.unlock();
// log.info("任务执行完毕,释放锁");
}
} catch (InterruptedException e) {
log.error("定时任务获取分布式锁异常", e);
}
}
最后
集群部署springboot应用时需要注意服务器时间是否一致,否则还是容易造成多台服务器定时任务多次执行的问题。