news 2026/4/15 23:15:50

Spring Boot 定时任务多实例互斥执行

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Spring Boot 定时任务多实例互斥执行

Spring Boot 的@Scheduled写定时任务很方便,但多实例部署时有个问题:同一个定时任务会在每台机器上都触发执行。

比如部署了两台应用服务器,凌晨 2 点的数据统计任务会同时跑两遍,数据重复、文件重复生成。

解决这个问题通常有几种思路。

常见方案

方案一:单机执行

只在一台指定的机器上跑任务:

@Scheduled(cron = "0 0 2 * * ?") public void scheduledTask() { String hostname = InetAddress.getLocalHost().getHostName(); if (!"app-server-01".equals(hostname)) { return; } // do something }

问题很明显:那台机器挂了,任务就不执行了。

方案二:Redis 分布式锁

用 Redis 的 SETNX 实现互斥(或者Redission):

@Scheduled(cron = "0 0 2 * * ?") public void scheduledTask() { Boolean locked = stringRedisTemplate.opsForValue() .setIfAbsent("task:data-sync", "1", 10, TimeUnit.MINUTES); if (Boolean.FALSE.equals(locked)) { return; } try { // do something } finally { stringRedisTemplate.delete("task:data-sync"); } }

能用,但每个任务都要写一遍加锁释放逻辑,而且需要项目里有 Redis。

ShedLock 方案

ShedLock 是一个专门解决定时任务重复执行问题的框架,支持多种存储后端(数据库、Redis、MongoDB 等)。

核心思路:在存储层记录每个任务的锁状态,任务执行前先抢锁,抢到了才执行。

集成步骤

1. 添加依赖

<dependency> <groupId>net.javacrumbs.shedlock</groupId> <artifactId>shedlock-spring</artifactId> <version>4.42.0</version> </dependency> <dependency> <groupId>net.javacrumbs.shedlock</groupId> <artifactId>shedlock-provider-jdbc-template</artifactId> <version>4.42.0</version> </dependency>

2. 创建锁表

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

3. 配置 LockProvider

@Configuration @EnableSchedulerLock(defaultLockAtMostFor = "10m") public class ShedLockConfig { @Bean public LockProvider lockProvider(DataSource dataSource) { return new JdbcTemplateLockProvider( JdbcTemplateLockProvider.Configuration.builder() .withDataSource(dataSource) .withTableName("shedlock") .build() ); } }

4. 给定时任务加注解

@Scheduled(cron = "0 0 2 * * ?") @SchedulerLock(name = "dataSyncTask", lockAtMostFor = "5m") public void syncData() { // do something }

完成。多台服务器部署时,只有抢到锁的那台会执行任务。

注解参数说明

@SchedulerLock有几个关键参数:

name:锁名称,相同 name 的任务会互斥执行。建议用任务名来命名,保持唯一。

lockAtMostFor:锁的最大持有时间。

这是为了防止任务执行过程中机器宕机,导致锁永远不释放。比如设置5m,即使任务执行超时,锁也会在 5 分钟后自动过期。

一般按任务预期执行时间的 2 倍左右设置,留些余量。

lockAtLeastFor:锁的最小持有时间。

这是为了防止任务执行太快,锁立即释放被其他机器抢到。

比如定时任务每分钟执行一次,任务 5 秒就跑完了。如果没有这个参数,其他机器可能会在同一分钟内再次抢到锁执行。

这种情况下可以设置lockAtLeastFor = "1m",确保锁保持到下一分钟。

实现原理

ShedLock 的实现逻辑不复杂。

任务执行前,会向数据库插入或更新锁记录:

INSERT INTO shedlock (name, lock_until, locked_at, locked_by) VALUES ('dataSyncTask', '2025-01-25 02:05:00', NOW(), '192.168.1.10') ON DUPLICATE KEY UPDATE lock_until = '2025-01-25 02:05:00', locked_at = NOW(), locked_by = '192.168.1.10' WHERE lock_until < NOW();

关键是最后的WHERE lock_until < NOW()条件:

  • • 如果当前锁已过期,UPDATE 成功,抢到锁

  • • 如果当前锁未过期,UPDATE 影响行数为 0,抢锁失败,任务不执行

任务执行完成后不需要主动释放锁,等待lock_until时间到期即可。

适用场景

ShedLock 的定位很明确:专门为定时任务设计的分布式锁框架。

适合

  • • 定时任务需要互斥执行,避免重复

  • • 希望用注解方式简化锁的代码逻辑

  • • 需要自动锁过期机制,防止死锁

不适合

  • • 高并发抢锁的业务场景(比如秒杀、库存扣减),ShedLock 不是为此设计

  • • 需要可重入锁、读写锁等复杂特性

  • • 需要精确控制锁获取和释放时机的业务逻辑

ShedLock 和通用分布式锁是互补关系,不是替代关系。如果你的业务代码里需要手动加锁解锁,用 Redisson 或手动实现 Redis SETNX 更合适。但如果只是为了解决定时任务重复执行的问题,ShedLock 是更简洁的方案。

几个注意事项

1. 存储后端选择

本文演示用的是 JDBC 方式(基于数据库表)。ShedLock 还支持 Redis、MongoDB、ZooKeeper、Hazelcast 等多种存储后端,根据项目现有技术栈选择即可。

2. 表名自定义(数据库存储时)

如果用 JDBC 作为存储后端,默认表名是shedlock,可以按需修改:
3. 机器标识

locked_by字段记录是哪台机器拿到的锁,默认是主机名。可以自定义成更有意义的标识:

.withLockedByValue("app-" + getServerIp())

4. 主从/多数据源场景(数据库存储时)

如果项目有多个数据源,确保 ShedLock 用的是主库,避免主从延迟导致的锁问题。

总结

ShedLock 是一个专门为定时任务设计的分布式锁框架:

  • • 优点:注解式使用、集成简单、自动锁过期、支持多种存储后端

  • • 局限性:只适用于定时任务场景,不适用于通用业务加锁

和手动写 Redis 分布式锁相比,ShedLock 把定时任务锁的逻辑抽象出来了,代码更简洁。但如果你需要的是通用业务锁,还是用 Redisson 或手写 SETNX 更合适。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/11 14:26:59

GPT-OSS-20B金融场景应用:智能投研系统搭建

GPT-OSS-20B金融场景应用&#xff1a;智能投研系统搭建 你是不是也遇到过这些情况&#xff1a; 每天要翻几十份PDF研报&#xff0c;却找不到关键数据点&#xff1b;上市公司财报一出&#xff0c;团队要花两三天才能整理出核心指标对比&#xff1b;行业新闻刷屏&#xff0c;但…

作者头像 李华
网站建设 2026/4/14 5:43:41

SSH隧道访问技巧,远程调试FSMN-VAD服务

SSH隧道访问技巧&#xff0c;远程调试FSMN-VAD服务 在实际语音处理项目中&#xff0c;我们经常需要在服务器上部署离线VAD&#xff08;Voice Activity Detection&#xff09;服务进行本地调试或团队协作。但受限于云平台的安全策略&#xff0c;Web服务默认无法直接对外暴露端口…

作者头像 李华
网站建设 2026/4/12 2:28:27

GPEN镜像快速上手:测试图+自定义图都能修

GPEN镜像快速上手&#xff1a;测试图自定义图都能修 你是不是也遇到过这些情况&#xff1a;老照片泛黄模糊、手机拍的人像有噪点、证件照不够清晰、社交平台上传的自拍照细节丢失&#xff1f;别急着找修图师&#xff0c;也别在PS里折腾半天——现在有一套开箱即用的人像修复方…

作者头像 李华
网站建设 2026/4/10 22:11:40

新手必看!Qwen-Image-Edit-2511保姆级部署与使用教程

新手必看&#xff01;Qwen-Image-Edit-2511保姆级部署与使用教程 1. 这不是普通修图工具&#xff0c;而是一个“能听懂你话”的AI图像编辑员 你有没有试过&#xff1a; 想把朋友圈里那张夏天的海边照&#xff0c;一键改成冬日雪景&#xff0c;连人物围巾都自动加厚&#xff…

作者头像 李华
网站建设 2026/4/16 0:33:45

保姆级教程:如何快速使用Face Fusion镜像完成照片修复

保姆级教程&#xff1a;如何快速使用Face Fusion镜像完成照片修复 1. 为什么你需要这张镜像——照片修复的现实痛点 你有没有遇到过这些情况&#xff1f; 找到一张珍贵的老照片&#xff0c;但人物面部有明显划痕、泛黄或模糊拍摄的合影中有人闭眼、表情僵硬&#xff0c;想换…

作者头像 李华
网站建设 2026/4/13 20:17:59

PCBA阻抗匹配设计原理及应用场景详解

以下是对您提供的博文内容进行 深度润色与结构优化后的版本 。本次改写严格遵循您的全部要求&#xff1a; ✅ 彻底去除AI痕迹 &#xff1a;语言自然、专业且具“人味”&#xff0c;避免模板化表达和空洞术语堆砌&#xff1b; ✅ 摒弃刻板标题体系 &#xff1a;删除所有…

作者头像 李华