当前位置: 首页 > news >正文

@SchedulerLock 防止分布式环境下定时任务并发执行

背景

在一个有多个服务实例的分布式系统中,如果你用 @Scheduled 来定义定时任务,所有实例都会执行这个任务。ShedLock 的目标是只让一个实例在某一时刻执行这个定时任务。

使用步骤

引入依赖

当前以redisTemplate为例子,MongoDB、Zookeeper、JDBC都可以但是需要建表

需要注意java1.8需要使用4.42.0,java17使用5.10.0不然会报错
Spring常见错误:类文件具有错误的版本 61.0, 应为 52.0

<dependency>
    <groupId>net.javacrumbs.shedlock</groupId>
    <artifactId>shedlock-provider-redis-redisson</artifactId>
    <version>4.42.0</version>
</dependency>
<dependency>
    <groupId>org.redisson</groupId>
    <artifactId>redisson-spring-boot-starter</artifactId>
    <version>4.42.0</version>
</dependency>

增加配置类

package com.platform.common.redis.configure;

import net.javacrumbs.shedlock.core.LockProvider;
import net.javacrumbs.shedlock.provider.redis.spring.RedisLockProvider;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;

@Configuration
public class ShedLockConfig {

    @Bean
    public LockProvider lockProvider(RedisConnectionFactory redisConnectionFactory) {
        // 创建 Redis 锁提供者,使用 RedisConnectionFactory
        return new RedisLockProvider(redisConnectionFactory);
    }
}

启用ShedLock,在启动类上增加@EnableSchedulerLock注解

@EnableSchedulerLock(defaultLockAtMostFor = "PT30S")
@SpringBootApplication
public class PlatFormRsyncApplication implements CommandLineRunner 

定时任务的使用,在@Scheduled下增加@SchedulerLock注解

需要注意所有@SchedulerLock修饰的方法必须为public,因为需要序列化

@Scheduled(fixedRateString = "${task.fsOrgPersonRsyncTask.fixedRate}")
@SchedulerLock(name = "myTask", lockAtMostFor = "PT30S", lockAtLeastFor = "PT5S")
public void fsOrgPersonRsyncTask() {

name:任务唯一标识(必须)

  • lockAtMostFor:最多锁定多久(即使服务挂了,锁也会过期)
  • lockAtLeastFor:至少锁定多久(任务执行太快也保持锁一段时间)

格式支持 ISO-8601,例如:

  • “PT30S” 表示 30 秒
  • “PT5M” 表示 5 分钟

工作原理

不需要手动创建 Redis key,ShedLock 会自动处理
在这里插入图片描述


锁的获取:

  • 当某个服务器尝试执行定时任务时,ShedLock 会尝试在 Redis 中为该任务设置一个锁(通过设置一个具有过期时间的键)。
  • 如果 Redis 中没有该锁,ShedLock 就会成功地为该任务设置锁,表明该服务器成功获得了执行任务的权限。
  • 如果 Redis 中已经存在该锁(表示其他服务器正在执行该任务),那么当前尝试获取锁的服务器就无法获取到锁。此时,该服务器不会执行任务,它会等待锁释放。

任务执行:

  • 获取到锁的服务器会执行定时任务。在任务执行期间,其他服务器无法获得锁,因此不能执行相同的任务。

锁的释放:

  • 任务执行完成后,获取到锁的服务器会释放锁(ShedLock 会自动处理锁的过期和释放)。锁的过期时间是由 lockAtMostFor 属性控制的,如果任务执行时间较短,锁会提前过期释放。

其他服务器:

  • 其他服务器一开始获取不到锁时会等到下次尝试。通常,它们会继续等待锁的释放,或者根据配置的定时任务周期(例如 @Scheduled(cron = “0 */1 * * * ?”))再次尝试获取锁。

相关文章:

  • 深度学习:AI 大模型时代的智能引擎
  • linux shell编程之条件语句(二)
  • 小试牛刀-抽奖程序
  • Git 查看提交历史
  • 多链协议和跨链桥
  • 如果单表数据量大,只能考虑分库分表吗
  • LangChain4j实战-Java AI应用开源框架之LangChain4j和Spring AI
  • 基于关键字定位的自动化PDF合同拆分
  • 榕壹云外卖跑腿系统:基于Spring Boot+MySQL+UniApp的智慧生活服务平台
  • SQL实战篇,数据库在Kooboo中的实际应用(一)
  • 《Vue Router实战教程》11.匹配当前路由的链接
  • 数据中台、BI业务访谈(三):如何选择合适的访谈对象
  • leetcode0155. 最小栈-medium
  • CRM软件介绍与10大主流产品选型指南
  • Umi Max 和 Ant Design Pro 的区别
  • [Windows] OfficeAI 助手 v0.3.20(长期免费,2025-03-18 本地支持WPS_Word联动)
  • 深入浅出:Linux Shell 中的条件判断与空变量检查
  • 网页布局思路
  • 【Django】教程-15-注册页面
  • [Effective C++]条款30:透彻了解inlining的里里外外
  • wordpress无插件下载/优化大师优化项目有
  • 帝国cms 做网站地图/黄石seo
  • sae部署wordpress/最新seo视频教程
  • 北京大型网站开发/百度一下网页版浏览器
  • 最新网站推广/seo教育
  • 做威客网的正规网站有哪些/优化公司