Spring Boot集成ShedLock实现分布式定时任务

news/2024/12/16 21:30:52/

1、什么是ShedLock?
ShedLock 是一个 Java 库,通常用于分布式系统中,确保定时任务(Scheduled Tasks)在集群环境下只被某一个实例执行一次。它通过在共享资源(例如数据库或分布式缓存)中添加锁的方式,避免多个实例同时执行相同的任务

ShedLock 的工作原理
1.分布式锁:

在任务开始时,ShedLock 会尝试在数据库(或其他存储)中创建一个锁。
如果某个实例成功获取锁,则只有它能执行该任务。

2.锁的生命周期:

锁会有一个明确的过期时间(锁的持有时间,lockAtLeastFor 和 lockAtMostFor 参数配置)。
锁过期后,即使任务异常终止,其他实例也可以重新获取锁。

3.支持的存储:

支持多种锁存储,包括数据库(如 MySQL、PostgreSQL)、Redis、MongoDB 等。

应用场景
1、分布式定时任务控制
分布式环境中,多个实例会同时调度定时任务。如果没有控制,可能导致任务重复执行。ShedLock 确保只有一个实例能运行任务。
例如:
生成日报表的定时任务。
清理过期数据的批处理任务。

2、避免重复任务执行
即使在单实例环境中,也可以使用 ShedLock 避免因意外重启或配置错误导致同一任务被多次触发。

3、事件驱动任务的幂等性
当某些任务需要对同一事件触发处理时,使用 ShedLock 可以确保一个事件只被处理一次。

4、任务重试机制
如果任务需要重试(例如在发生错误时),ShedLock 能避免多个实例同时重试相同任务。

2、代码工程

实验目的
使用ShedLock 来确保在分布式环境中只有一个实例能运行任务

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.2.1</version></parent><modelVersion>4.0.0</modelVersion><artifactId>shedlock</artifactId><properties><maven.compiler.source>17</maven.compiler.source><maven.compiler.target>17</maven.compiler.target></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-autoconfigure</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>net.javacrumbs.shedlock</groupId><artifactId>shedlock-spring</artifactId><version>5.5.0</version></dependency><dependency><groupId>net.javacrumbs.shedlock</groupId><artifactId>shedlock-provider-jdbc-template</artifactId><version>5.5.0</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.33</version></dependency></dependencies>
</project>

config

package com.demo.config;import net.javacrumbs.shedlock.core.LockProvider;
import net.javacrumbs.shedlock.provider.jdbctemplate.JdbcTemplateLockProvider;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;import javax.sql.DataSource;@Configuration
public class ShedLockConfig {@Beanpublic LockProvider lockProvider(DataSource dataSource) {return new JdbcTemplateLockProvider(JdbcTemplateLockProvider.Configuration.builder().withJdbcTemplate(new JdbcTemplate(dataSource)).usingDbTime() // Works with PostgreSQL, MySQL, MariaDb, MS SQL, Oracle, HSQL, H2, DB2, and others.build());}
}

cron

package com.demo.cron;import net.javacrumbs.shedlock.spring.annotation.EnableSchedulerLock;
import net.javacrumbs.shedlock.spring.annotation.SchedulerLock;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;@Configuration
@EnableScheduling
@EnableSchedulerLock(defaultLockAtMostFor = "PT30S")
public class SchedulerConfig {@Scheduled(cron = "0 0/1 * * * ?")@SchedulerLock(name = "scheduledTaskName", lockAtMostFor = "PT10M", lockAtLeastFor = "PT1M")public void scheduledTask() {//  some logic codeSystem.out.println("Executing scheduled task");}}

@Scheduled(cron = “0 0/1 * * * ?”)

1、定义定时任务的调度时间。

2、表达式含义:任务每分钟的整点触发,例如 12:00、12:01、12:02。

3、注意:多个实例(分布式环境)都会在同一时间调度到此任务,但通过 ShedLock 确保只有一个实例能真正执行。

@SchedulerLock

1、锁的最短持有时间为 1分钟。

2、即使任务提前完成,锁仍会持有至少 1 分钟,防止其他实例快速重复执行任务。

3、锁的最长持有时间为 10分钟。

4、如果任务运行超出 10 分钟,即使没有主动释放锁,也会自动过期,其他实例可以继续获取锁。

5、定义锁的唯一标识。共享存储(如数据库或 Redis)中会记录此锁的状态。

6、使用 ShedLock 来管理分布式锁。

7、name = “scheduledTaskName”:

8、lockAtMostFor = “PT10M”:

9、lockAtLeastFor = “PT1M”:

任务逻辑

1、System.out.println(“Executing scheduled task”); 是任务的业务逻辑。

2、此逻辑只会在获得锁的实例上执行。

配置文件
node1节点

spring.datasource.url=jdbc:mysql://127.0.0.1:3306/demo?useUnicode=true&characterEncoding=utf-8&useSSL=false
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
server.port=8081

node2节点

spring.datasource.url=jdbc:mysql://127.0.0.1:3306/demo?useUnicode=true&characterEncoding=utf-8&useSSL=false
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
server.port=8082

3、测试
1、启动node1节点
java -jar myapp.jar --spring.profiles.active=node1

2、启动node2节点
java -jar myapp.jar --spring.profiles.active=node2

通过控制台观察日志,可以发现,2个实例交替获取到锁执行,而不是同一时刻一起执行

4、注意事项

  • 任务时间控制: 确保任务的实际执行时间小于 lockAtMostFor,否则任务可能被其他实例重复执行。

  • 幂等性: 任务逻辑应尽量设计为幂等的(重复执行不会产生副作用),以应对锁机制的潜在异常情况。

  • 存储配置: 确保使用高可用的锁存储(如数据库或 Redis),否则锁机制可能失效。


http://www.ppmy.cn/news/1555681.html

相关文章

人工智能大语言模型起源篇,低秩微调(LoRA)

上一篇: 《规模法则&#xff08;Scaling Law&#xff09;与参数效率的提高》 序言&#xff1a;您在找工作时会不会经常听到LoRA微调&#xff0c;这项技术的来源就是这里了。 &#xff08;12&#xff09;Hu、Shen、Wallis、Allen-Zhu、Li、L Wang、S Wang 和 Chen 于2021年发表…

Matlab笔记---clear、clc、clear all应用

在MATLAB中&#xff0c;clear、clc 和 clear all 是三个常用的命令&#xff0c;它们各自有不同的作用&#xff1a; clc&#xff1a; clc 命令用于清除MATLAB命令窗口中的所有输出。它不会删除任何变量、函数或文件&#xff0c;只是清除屏幕上的显示内容&#xff0c;让你可以更…

并行口的基本概念

单片机的并行口结构包括多个并行I/O端口&#xff0c;用于与外部设备进行并行数据传输。这些端口能够直接读写外部存储器、显示设备、打印机等外设的数据&#xff0c;是单片机与外界交互的重要通道。在深入探讨之前&#xff0c;我们先简要了解下单片机的基本概念。 单片机&…

Next.js 指令教程:深入理解 use-server 指令

更多有关Next.js教程&#xff0c;请查阅&#xff1a; 【目录】Next.js 独立开发系列教程-CSDN博客 目录 1. 概述 2. use-server 指令概述 2.1 什么是 use-server 指令&#xff1f; 2.2 为什么需要 use-server&#xff1f; 3. use-server 工作原理 3.1 渲染过程 3.2 动态…

《深入浅出HTTPS​​​​​​​​​​​​​​​​​》读书笔记(19):密钥

为了避免暴力破解&#xff0c;不同密码学算法的密钥应该保证一定长度&#xff0c;密钥长度足够长也不代表安全&#xff0c;密钥应该是随机、无法预测的。 从两个维度考虑&#xff1a; ◎对称加密算法、MAC算法使用的密钥就是一串数字。 ◎公开密钥算法中的密钥是一对&#x…

机器人通信:通信方式、协议、类型、场景

机器人通信是指机器人之间、机器人与人类或机器人与其他系统之间的信号传递和信息交换。其目的是实现协作、控制、监测和数据共享。以下是一些关键点&#xff1a; 通信方式&#xff1a; 无线通信&#xff1a;使用无线电波&#xff08;如Wi-Fi、蓝牙、ZigBee等&#xff09;进行数…

【银河麒麟高级服务器操作系统】有关dd及cp测试差异的现象分析详解

了解更多银河麒麟操作系统全新产品&#xff0c;请点击访问 麒麟软件产品专区&#xff1a;https://product.kylinos.cn 开发者专区&#xff1a;https://developer.kylinos.cn 文档中心&#xff1a;https://documentkylinos.cn dd现象 使用银河麒麟高级服务器操作系统执行两次…

使用docker-compose部署fastApi微服务

制作镜像 准备服务代码man.py 文件夹结构 import os from loguru import logger from fastapi import FastAPI import uvicornapp FastAPI() # 定义日志输出目录 log_directory os.getenv("LOG", "/work/logs/") os.makedirs(log_directory, exist_o…