SpringBoot整合ShedLock解决定时任务防止重复执行的问题

 更新时间:2025年01月24日 10:00:09   作者:❀͜͡傀儡师  
ShedLock是一个用于分布式系统中防止定时任务重复执行的库,本文主要介绍了SpringBoot整合ShedLock解决定时任务防止重复执行的问题,具有一定的参考价值,感兴趣的可以了解一下

在分布式系统中,尤其是涉及到定时任务的场景下,任务的重复执行是一个常见问题。例如,多个服务节点同时执行同一个定时任务,可能会导致数据重复处理或者资源争用。ShedLock 是一个解决分布式环境中定时任务重复执行问题的库,它通过使用数据库锁机制确保只有一个节点执行特定的定时任务。

ShedLock 的工作原理

ShedLock 通过对任务加锁来避免多个实例(多个节点)执行同一个定时任务。它依赖于数据库表来存储任务的锁信息。每次执行任务之前,ShedLock 会检查数据库中是否有其他节点已经获得锁。如果没有,它会设置锁并执行任务;如果有,任务会被跳过。

添加依赖

在 Spring Boot 项目中集成 ShedLock,需要在 pom.xml 中添加相关依赖。

<dependencies>
    <!-- ShedLock核心库 -->
    <dependency>
        <groupId>net.javacrumbs.shedlock</groupId>
        <artifactId>shedlock-spring</artifactId>
        <version>6.2.0</version> <!-- 最新版本 -->
    </dependency>

    <!-- ShedLock数据库存储实现(JPA) -->
    <dependency>
        <groupId>net.javacrumbs.shedlock</groupId>
        <artifactId>shedlock-provider-jpa</artifactId>
        <version>6.2.0</version> <!-- 最新版本 -->
    </dependency>

    <!-- Spring Boot JPA 支持 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>

    <!-- 选择合适的数据库,例如 H2 或 MySQL -->
    <dependency>
        <groupId>com.h2database</groupId>
        <artifactId>h2</artifactId>
        <scope>runtime</scope>
    </dependency>
</dependencies>

创建数据库表

在使用 ShedLock 时,需要创建一个数据库表来存储锁的状态。以下是示例的 SQL 脚本,适用于 MySQL 或其他关系型数据库。

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

配置 ShedLock 数据源

然后,在 Spring Boot 配置类中启用 ShedLock,配置数据库存储和锁提供者。

配置类 ShedLockConfig.java:

import net.javacrumbs.shedlock.core.LockProvider;
import net.javacrumbs.shedlock.provider.jparepository.JpaLockProvider;
import net.javacrumbs.shedlock.spring.annotation.EnableSchedulerLock;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;

import javax.persistence.EntityManager;
import javax.sql.DataSource;

@Configuration
@EnableSchedulerLock(defaultLockAtMostFor = "PT30M")  // 默认任务最长执行时间 30 分钟
@EnableJpaRepositories("net.javacrumbs.shedlock.provider.jparepository") // 启用 JPA 存储库
public class ShedLockConfig {

    @Bean
    public LockProvider lockProvider(EntityManager entityManager) {
        return new JpaLockProvider(entityManager); // 使用 JPA 实现的锁提供者
    }
}

创建定时任务

接下来,你可以通过 @Scheduled 注解定义定时任务,并使用 @SchedulerLock 注解来确保任务不会在多个节点上同时执行。

示例:定时任务 ScheduledTasks.java:

import net.javacrumbs.shedlock.spring.annotation.SchedulerLock;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@Component
public class ScheduledTasks {

    // 每分钟执行一次任务,使用 ShedLock 确保任务不会被重复执行
    @Scheduled(cron = "0 * * * * ?")
    @SchedulerLock(name = "exampleTask", lockAtMostFor = "PT30S", lockAtLeastFor = "PT30S")
    public void exampleTask() {
        System.out.println("Executing example task...");
        // 任务逻辑,例如更新数据、发送通知等
    }
}

在上述代码中,@SchedulerLock 注解通过 name 参数来标识任务名称,确保相同名称的任务只会由一个节点执行。lockAtMostFor 和 lockAtLeastFor 分别表示任务最多和最少保持锁定的时间,防止任务执行时间过短或过长。

  • lockAtMostFor:设置任务执行时,最多持有锁的时间。如果任务执行时间超过该时间,锁将被释放。
  • lockAtLeastFor:设置任务至少持有锁的时间,防止任务执行过快而过早释放锁。

启用 Spring Boot 定时任务功能

确保启用了 Spring Boot 的定时任务功能。你可以在 application.properties 或 application.yml 中配置相关属性,或者在启动类中启用 @EnableScheduling。

application.properties 配置:

spring.scheduling.enabled=true

或者在主启动类上使用 @EnableScheduling 注解启用定时任务:

主启动类 SpringBootApplication.java:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;

@SpringBootApplication
@EnableScheduling
public class SpringBootApplication {

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

工作原理

锁定任务:当定时任务被触发时,ShedLock 会尝试获取锁。如果任务已经有锁,其他节点会跳过该任务的执行。
分布式锁:通过数据库表,ShedLock 确保分布式环境中多个服务实例不会同时执行相同的任务,避免了重复执行的问题。
防止任务阻塞:如果任务执行时间过长,ShedLock 会根据配置自动释放锁,防止任务被阻塞。

其他配置

你可以通过配置 defaultLockAtMostFor 和 defaultLockAtLeastFor 来全局设置锁的过期时间。defaultLockAtMostFor 表示全局配置的任务最长执行时间,defaultLockAtLeastFor 则表示全局配置的任务最短执行时间。

@EnableSchedulerLock(defaultLockAtMostFor = "PT30M", defaultLockAtLeastFor = "PT30S")

这样,所有使用 @SchedulerLock 注解的任务都将遵循这些全局设置,除非你在注解中显式地覆盖它们。

在 ShedLock 6.2.0 中,集成方式没有太大变化,但提供了更强的配置灵活性和优化。在分布式系统中,ShedLock 可以确保定时任务只会被一个实例执行,有效避免了重复执行的问题。通过数据库存储锁,ShedLock 使得定时任务管理更加可靠,适用于高并发和分布式的应用场景。

通过上述步骤,你可以轻松地在 Spring Boot 项目中使用 ShedLock 来管理定时任务,确保任务不会被重复执行,提升系统的稳定性和性能。

到此这篇关于SpringBoot整合ShedLock解决定时任务防止重复执行的问题的文章就介绍到这了,更多相关SpringBoot ShedLock防止重复执行内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • idea工具配置隐藏文件及文件夹方式

    idea工具配置隐藏文件及文件夹方式

    这篇文章主要介绍了idea工具配置隐藏文件及文件夹方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-08-08
  • 设计模式之构建(Builder)模式 建造房子实例分析

    设计模式之构建(Builder)模式 建造房子实例分析

    构建模式主要用来针对复杂产品生产,分离部件构建细节,以达到良好的伸缩性,考虑到设计模式来源于建筑学,因此举一个建造房子的例子,需要的朋友可以参考下
    2012-12-12
  • Java四种访问控制修饰符知识点总结

    Java四种访问控制修饰符知识点总结

    本篇文章给大家详细分析了Java四种访问控制修饰符的相关知识点,有兴趣的朋友可以参考学习下。
    2018-03-03
  • SpringBoot在RequestBody中使用枚举参数案例详解

    SpringBoot在RequestBody中使用枚举参数案例详解

    这篇文章主要介绍了SpringBoot在RequestBody中使用枚举参数案例详解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-09-09
  • Spring中byName和byType的区别及说明

    Spring中byName和byType的区别及说明

    这篇文章主要介绍了Spring中byName和byType的区别及说明,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-12-12
  • gradle安装配置以及使用最新方法

    gradle安装配置以及使用最新方法

    这篇文章主要给大家介绍了关于gradle安装配置以及使用的相关资料,Gradle是一个基于ApacheAnt和ApacheMaven概念的项目自动化构建开源工具,文中通过图文介绍的非常详细,需要的朋友可以参考下
    2023-11-11
  • JSONArray在Java中的应用操作实例

    JSONArray在Java中的应用操作实例

    JSONArray是org.json库用于处理JSON数组的类,可将Java对象(Map/List)转换为JSON格式,提供增删改查等操作,适用于前后端数据交互,并涵盖安全、性能优化及最佳实践,本文给大家介绍JSONArray在Java中的应用,感兴趣的朋友一起看看吧
    2025-07-07
  • SpringBoot使用RestTemplate实现HTTP请求详解

    SpringBoot使用RestTemplate实现HTTP请求详解

    这篇文章主要为大家详细介绍了SpringBoot如何使用RestTemplate实现进行HTTP请求,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下
    2024-03-03
  • Java中@JSONField注解的使用详解

    Java中@JSONField注解的使用详解

    这篇文章主要介绍了Java中@JSONField注解的使用,@JSONField是阿里巴巴开源的JSON处理库FastJSON提供的一个注解,用于在Java对象和JSON数据之间进行序列化和反序列化时,对字段的行为进行更精细的控制,需要的朋友可以参考下
    2025-05-05
  • Java实现手写自旋锁的示例代码

    Java实现手写自旋锁的示例代码

    自旋锁是专为防止多处理器并发而引入的一种锁,它在内核中大量应用于中断处理等部分。本文将用Java实现手写自旋锁,需要的可以参考一下
    2022-08-08

最新评论