我们在项目中经常要用到定时任务,当有天服务器压力过大,我们就会增加服务器的数量,这时每台服务器的定时任务都在同一时间运行,导致我们需要同一时间运行一次的定时任务跑了多次,这时就需要解决这个问题,就用到了 shedlock
下面这是我项目里写的定时任务,里面的方法没有写出来
@Component
public class TimeOutSMSScheduledLock {
@Autowired
public TimeOutSMSService timeOutSMSService;
//这时定时任务
@Scheduled(cron = "0 0 9,14 * * ?")
public void sendSMS(){
//具体的方法我就不写了,你可以随便写也可以打印日志
timeOutSMSService.timeOutSendSMS();
}
}
<dependency>
<groupId>net.javacrumbs.shedlock</groupId>
<artifactId>shedlock-spring</artifactId>
<version>2.2.0</version>
</dependency>
<dependency>
<groupId>net.javacrumbs.shedlock</groupId>
<artifactId>shedlock-provider-jdbc-template</artifactId>
<version>2.2.0</version>
</dependency>
@Configuration
public class ScheduledLockConfig
{
@Bean
public LockProvider lockProvider(DataSource dataSource) {
return new JdbcTemplateLockProvider(dataSource);
}
}
CREATE TABLE `shedlock` (
`name` varchar(64) NOT NULL DEFAULT '',
`lock_until` timestamp NULL DEFAULT NULL,
`locked_at` timestamp NULL DEFAULT NULL,
`locked_by` varchar(255) DEFAULT NULL,
PRIMARY KEY (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
里面有四个字段
主键name:每个定时任务的一个名字
locked_at:锁的开始时间
lock_until:锁的结束时间
再定时开始时,会更新这两个时间,在时间之内的定时是不会被执行的
@SpringBootApplication
//启用自带定时任务
@EnableScheduling
//定时任务锁
//defaultLockAtMostFor 指定在执行节点结束时应保留锁的默认时间使用ISO8601 Duration格式
//作用就是在被加锁的节点挂了时,无法释放锁,造成其他节点无法进行下一任务
//这里默认30s
@EnableSchedulerLock(defaultLockAtMostFor = "PT30S")
public class CmccVoicesApiApplication {
public static void main(String[] args) {
SpringApplication.run(CmccVoicesApiApplication.class, args);
}
}
@Component
public class TimeOutSMSScheduledLock {
@Autowired
public TimeOutSMSService timeOutSMSService;
//这是定时任务
@Scheduled(cron = "0 0 9,14 * * ?")
//参数自己根据情况设置
@SchedulerLock(name = "sugExpiredSMS", lockAtMostFor = 1000*60*60*10, lockAtLeastFor = 1000*60*60*5)
public void sendSMS(){
//具体的方法我就不写了,你可以随便写也可以打印日志
timeOutSMSService.timeOutSendSMS();
}
}
name:定时任务的名字,就是数据库中的内个主键
lockAtMostFor:锁的最大时间单位为毫秒
lockAtMostForString:最大时间的字符串形式,例如:PT30S 代表30秒
lockAtLeastFor:锁的最小时间单位为毫秒
lockAtLeastForString:最小时间的字符串形式
<!-- 分布式定时任务锁 -->
<!-- https://mvnrepository.com/artifact/net.javacrumbs.shedlock/shedlock-spring -->
<dependency>
<groupId>net.javacrumbs.shedlock</groupId>
<artifactId>shedlock-spring</artifactId>
<version>4.0.4</version>
</dependency>
<!-- 使用redis做分布式任务 -->
<dependency>
<groupId>net.javacrumbs.shedlock</groupId>
<artifactId>shedlock-provider-redis-spring</artifactId>
<version>2.5.0</version>
@Configuration
@EnableSchedulerLock(defaultLockAtMostFor = "PT30M")
public class ShedLockConfig {
@Bean
public LockProvider lockProvider(RedisTemplate redisTemplate) {
return new RedisLockProvider(redisTemplate.getConnectionFactory());
}
@SpringBootApplication
//这个是定时任务,必须要有
@EnableScheduling
public class AppsApplication {
public static void main(String[] args) {
SpringApplication.run(AppsApplication .class, args);
}
@Component
public class TimeOutSMSScheduledLock {
@Autowired
public TimeOutSMSService timeOutSMSService;
//这是定时任务
@Scheduled(cron = "0 0 9,14 * * ?")
//参数自己根据情况设置
@SchedulerLock(name = "sugExpiredSMS", lockAtMostFor = 1000*60*60*10, lockAtLeastFor = 1000*60*60*5)
public void sendSMS(){
//具体的方法我就不写了,你可以随便写也可以打印日志
timeOutSMSService.timeOutSendSMS();
}
}