[057][调度模块]分布式环境下定时任务的防重复执行方案

简介: 本文介绍分布式定时任务防重复执行方案,基于Redis/Redisson分布式锁,提供自动续期与固定租期两种模式,通过`key()`控制锁粒度,支持异常跳过与自定义处理,确保集群中同一任务仅单点执行。代码开源。

[057][调度模块]分布式环境下定时任务的防重复执行方案

本文章代码: gitee , gitcode , github

摘要

在集群部署中,同一个定时任务可能在多台机器上同时触发,造成资源浪费或数据错误。本文基于提供的 AutoRenewalLockTaskRunnerFixedLeaseLockTaskRunner 系列接口,阐述如何利用 Redis/Redisson 分布式锁包装任务执行,确保同一时刻只有一个节点执行任务。

1. 任务接口设计

框架定义了多个锁装饰器接口,业务实现只需继承相应接口并实现 doRun()

// Redis 自动续期锁
public interface AutoRenewalLockTaskRunner extends TaskRunner, Lockable {
   
    @Override
    default void run(Map<String, String> params) {
   
        RedisLockService.instance.autoRenewal()
            .doInLock(key(), () -> doRun(params));
    }
    void doRun(Map<String, String> params);
    // key() 定义锁的标识,如 "task:order:sync"
}

类似地,还提供了:

  • FixedLeaseLockTaskRunner(Redis 固定租期)
  • AutoRenewalBlockLockTaskRunner(Redisson 阻塞+自动续期)
  • FixedLeaseReentrantLockTaskRunner(Redisson 可重入+固定租期)

2. 两种锁模式对比

模式 适用场景 Redis 实现 Redisson 实现
固定租期 任务执行时间稳定且较短 SET NX PX + 不续期 lock(leaseTime)
自动续期 任务执行时间不确定或较长 定时任务每 5s 续期 lock()(看门狗机制)

3. 锁的粒度控制

Lockable 接口要求实现类提供 key() 方法,通常按任务名称或业务 ID 区分:

@Override
public String key() {
   
    return "schedule:lock:" + getTaskName(); // 例如通过构造函数注入
}

4. 异常处理

  • 若获取锁失败(如已被其他节点占用),会抛出 LockCreateException,任务直接跳过,不会影响下次调度。
  • 可覆盖 handleException(LockException) 方法自定义失败处理(如记录日志、发送告警)。

5. 集群效果

所有节点使用相同的锁 key,第一个获得锁的节点执行,其他节点快速失败,保证任务在集群内单点运行。

目录
相关文章
|
1月前
|
存储 安全 Java
[055][调度模块]Spring动态任务调度框架的设计与实现
本文设计并实现了一个基于Spring的动态任务调度框架,突破`@Scheduled`静态限制,支持运行时增删改任务、配置热加载及执行状态跟踪。核心采用`SchedulingConfigurer`与`TriggerTask`,解耦任务逻辑与调度机制,具备零侵入、线程安全、优雅停机等特性。(239字)
142 2
|
1月前
|
存储 安全 数据安全/隐私保护
如何搭建企业网盘?一位CTO的完整技术复盘
本文为CTO亲历复盘,从存储架构、智能检索、安全体系、知识管理四维度详解企业网盘搭建:强调其本质是“知识管理”而非单纯存储;涵盖MinIO/Ceph选型、冷热分层降本55%、BM25+向量混合检索、物理级数据隔离、知识图谱与RAG落地等关键技术实践。(239字)
103 4
|
3月前
|
SQL 人工智能 关系型数据库
自助分析平台搭好了,为什么业务还是天天找数据?聊聊权限、模板与联邦查询那些坑
自助分析平台搭好了,为什么业务还是天天找数据?聊聊权限、模板与联邦查询那些坑
188 3
|
1月前
|
存储 缓存 NoSQL
[038][验证码模块]基于 Hutool 的 Spring Boot 验证码组件设计与实现
本文介绍基于Hutool与Spring Boot深度集成的验证码组件,支持线段、圆圈、扭曲、GIF四类验证码,具备自动配置、多级缓存(Caffeine+Redis)、高斯模糊增强、忽略大小写校验及一次性使用等特性,架构清晰、扩展性强,开箱即用。
69 2
|
1月前
|
消息中间件 Prometheus 监控
[058][调度模块]任务生命周期事件与监听器机制
本文介绍调度模块的任务生命周期事件机制,通过`ChangeStatusEvent`事件与`ChangeStatusEventConsumer`监听器,实现任务状态(CREATED/STARTED/COMPLETED等)变更的灵活监听。支持日志、持久化、消息推送等扩展,具备高解耦性与异常隔离能力。(239字)
69 2
|
2月前
|
缓存 Java 数据库连接
[053][核心模块]Java枚举缓存与ORM集成实践
本文介绍Java枚举缓存与ORM(MyBatis/JPA)的通用集成方案:通过`EnumCache`双向哈希缓存(O(1)查找)、`BaseEnum`统一接口及自动注册的类型转换器,解决枚举查值性能低、重复编码、缓存不一致等痛点,提升可维护性与运行效率。(239字)
172 3
|
1月前
|
缓存 NoSQL 安全
[036][缓存模块]基于 Redis 自定义缓存锁的设计与实现
本文介绍基于Redis的轻量级分布式缓存锁组件,通过`@RedisLockable`注解+ AOP + Lua脚本,支持固定租期与自动续期双模式,解决缓存击穿、重复计算与资源竞争问题,具备声明式、动态Key、原子性及安全释放等特性,代码开源可扩展。(239字)
82 2
|
2月前
|
SQL Java 数据库连接
[026][数据模块]基于 MyBatis Plus 的企业级数据访问框架设计与实现
本文介绍基于MyBatis Plus二次封装的企业级数据访问框架,支持多租户隔离、分页、乐观锁、SQL防攻击及审计字段自动填充。通过有序拦截器链、条件化配置与开放扩展点,实现可插拔、易维护的统一数据访问能力。(239字)
167 2
|
1月前
|
缓存 安全 Java
[034][公共模块]基于SpEL的方法参数表达式求值器设计与实现
本文设计并实现了基于Spring SpEL的`MethodBasedExpressionEvaluator`,支持方法参数自动映射、占位符解析、Bean引用、自定义变量注入及表达式缓存,具备类型安全、线程安全与高扩展性,适用于权限控制、日志模板、缓存Key生成等场景。(239字)
97 2
|
2月前
|
存储 缓存 NoSQL
[033][缓存模块]基于 Redisson 的租户隔离 Redis Key 前缀设计
本文介绍基于Redisson的多租户Redis Key隔离方案:通过函数式接口`RedisKeyPrefix`与`NameMapper`扩展,自动为Key添加租户前缀(如`tenant1:user:123`),实现无侵入、高性能、可扩展的逻辑隔离,兼容锁/集合等全部Redisson功能。(239字)
94 1