知識庫 / Spring RSS 訂閱

使用Spring的ShedLock指南

Spring
HongKong
2
01:34 PM · Dec 06 ,2025

1. 概述

Spring 提供了一種便捷的方式來實現作業調度 API。 在我們部署多個應用程序實例時,它表現良好。

Spring 默認情況下無法處理多個實例之間的調度器同步。 相反,它會在每個節點上同時執行作業。

在本簡短教程中,我們將探討 ShedLock,這是一個 Java 庫,它確保在同一時間僅運行一次計劃任務,並且是 Quartz 的替代方案。

2. Maven 依賴

要使用 ShedLock 與 Spring 一起使用,我們需要添加 shedlock-spring 依賴項:

<dependency>
    <groupId>net.javacrumbs.shedlock</groupId>
    <artifactId>shedlock-spring</artifactId>
    <version>6.3.1</version>
</dependency>

我們可以從 Maven 中央倉庫 獲取最新版本。

3. 配置

ShedLock 僅在具有共享數據庫的環境中有效,需要聲明合適的 LockProvider

它會在數據庫中創建一個表或文檔,用於存儲當前鎖的信息。

目前,ShedLock 支持 Mongo、Couchbase、Elasticsearch、Redis、Hazelcast、ZooKeeper、Cassandra 以及任何具有 JDBC 驅動程序的系統。

對於本示例,我們將使用內存中的 H2 數據庫。

為了使其工作,我們需要提供 H2 數據庫ShedLock JDBC 依賴項

<dependency>
    <groupId>net.javacrumbs.shedlock</groupId>
    <artifactId>shedlock-provider-jdbc-template</artifactId>
    <version>6.3.1</version>
</dependency>
<dependency>
     <groupId>com.h2database</groupId>
     <artifactId>h2</artifactId>
     <version>2.1.214</version>
</dependency>

接下來,我們需要為 ShedLock 創建一個數據庫表,用於存儲調度器鎖的信息:

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

我們應該在 Spring Boot 應用程序的屬性文件中聲明數據源,以便 DataSource bean 可以通過 Autowired 注入。

這裏,我們使用 application.yml 來定義 H2 數據庫的數據源:

spring:
  datasource:
    driverClassName: org.h2.Driver
    url: jdbc:h2:mem:shedlock_DB;INIT=CREATE SCHEMA IF NOT EXISTS shedlock;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
    username: sa
    password:

讓我們配置 LockProvider,使用上面提供的數據庫配置。

Spring 可以使它變得非常簡單:

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

我們還需要提供以下配置要求:在我們的 Spring 配置類上添加 @EnableScheduling@EnableSchedulerLock 註解:

@SpringBootApplication
@EnableScheduling
@EnableSchedulerLock(defaultLockAtMostFor = "PT30S")
public class SpringBootShedlockApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringBootShedlockApplication.class, args);
    }
}

defaultLockAtMostFor 參數指定在執行節點發生故障時鎖應保持的默認時間。它使用 ISO8601 持續時間 格式。

在下一部分,我們將看到如何覆蓋此默認值。

4. 創建任務

為了創建由 ShedLock 處理的計劃任務,我們只需在方法上添加 <em @Scheduled</em><em @SchedulerLock</em> 註解:

@Component
class BaeldungTaskScheduler {

    @Scheduled(cron = "0 0/15 * * * ?")
    @SchedulerLock(name = "TaskScheduler_scheduledTask", 
      lockAtLeastFor = "PT5M", lockAtMostFor = "PT14M")
    public void scheduledTask() {
        // ...
    }
}

首先,讓我們來看一下@Scheduled。它支持基於cron格式的表達式,其中該表達式表示“每15分鐘一次”。

接下來,讓我們看看@SchedulerLockname參數必須唯一,而ClassName_methodName通常足以實現這一點。我們不想讓這個方法的運行超過一次,ShedLock使用唯一的名稱來實現這一點。

我們還添加了幾個可選參數。

首先,我們添加了lockAtLeastFor,以便在方法調用之間增加一些距離。使用“PT5M”表示該方法至少持有鎖5分鐘。換句話説,這意味着該方法最多由ShedLock每5分鐘運行一次。

接下來,我們添加了lockAtMostFor,用於指定在執行節點宕機時鎖應保持多久。使用“PT14M”表示鎖最多保持14分鐘。

在正常情況下,ShedLock在任務完成後直接釋放鎖。由於默認已在@EnableSchedulerLock中提供,因此我們不需要這樣做,但我們在這裏選擇覆蓋該默認值。

5. 結論

在本文中,我們學習瞭如何使用 ShedLock 創建和同步計劃任務。

user avatar
0 位用戶收藏了這個故事!
收藏

發佈 評論

Some HTML is okay.