Skip to content

@Schedule 通过 ShedLock 实现分布式定时任务

🏷️ Spring Boot ShedLock

默认的 @Schedule 注解实现的定时任务是单个应用的,当开启了多个实例,每个实例中都会执行一次。
此时可通过添加 shedlock-spring 包来支持这种分布式场景。

1. 在 pom.xml 中添加依赖

这里使用的版本是 4.20.1

xml
<!-- ShedLock -->
<dependency>
    <groupId>net.javacrumbs.shedlock</groupId>
    <artifactId>shedlock-spring</artifactId>
    <version>${shedlock.version}</version>
</dependency>
<dependency>
    <groupId>net.javacrumbs.shedlock</groupId>
    <artifactId>shedlock-provider-jdbc-template</artifactId>
    <version>${shedlock.version}</version>
</dependency>

2. 添加配置文件

@EnableScheduling 注解用于启用定时任务。
@EnableSchedulerLock 注解用于启用 ShedLock

这里使用数据库来实现任务的锁竞争,所以定义了一个 JdbcTemplateLockProvider 类型的 Bean

更多的锁实现方式请参考 这篇文章

java
import net.javacrumbs.shedlock.core.LockProvider;
import net.javacrumbs.shedlock.provider.jdbctemplate.JdbcTemplateLockProvider;
import net.javacrumbs.shedlock.spring.annotation.EnableSchedulerLock;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;

import javax.sql.DataSource;

/**
 * @author jiajia
 */
@Configuration
@EnableScheduling
@EnableSchedulerLock(defaultLockAtMostFor = "PT30S")
public class ShedLockConfiguration {

    @Bean
    public LockProvider lockProvider(DataSource dataSource) {
        return new JdbcTemplateLockProvider(dataSource);
    }
}

3. 创建数据库表

使用数据库锁时需要创建对应的表。

sql
CREATE TABLE shedlock(
  name VARCHAR(64),
  lock_until TIMESTAMP(3) NULL,
  locked_at TIMESTAMP(3) NULL,
  locked_by  VARCHAR(255),
  PRIMARY KEY (name)
)

4. 创建定时任务

注解的属性值使用了 SpEL ,以方便在配置中心中修改。

lockAtMostFor:锁最长保留时间(防止某个应用实例宕机导致锁被长时间占用)
lockAtLeastFor:锁最短保留时间(防止多个应用实例间有时间差)

java
@Scheduled(cron = "${task.sample.cron:0 0/10 * * * ?}")
@SchedulerLock(name = "sample-task",
        lockAtMostFor = "${task.sample.lock-at-most-for:60s}",
        lockAtLeastFor = "${task.sample.lock-at-least-for:10s}")
public void sampleTask() {
    // do something
}

参考

  1. SpringBoot 集成 ShedLock 实现分布式定时锁
  2. ShedLock 锁,防止 spring 定时调度@Scheduled 注解在分布式环境下重复执行