[057][调度模块]分布式环境下定时任务的防重复执行方案
本文配套代码: gitee , gitcode , github
![[057][调度模块]分布式环境下定时任务的防重复执行方案](/uploadfile/2026/0814/dacc4b90c4f7f883d70217c3d0f70d18.webp)
摘要
在分布式集群部署场景中,同一个定时任务、调度任务或 Cron 任务,往往可能被多台服务节点同时触发执行。轻则造成重复执行和资源浪费,重则引发数据重复处理、状态错乱甚至业务异常。本文将围绕提供的 AutoRenewalLockTaskRunner 和 FixedLeaseLockTaskRunner 等系列接口,说明如何通过 Redis/Redisson 分布式锁对任务执行过程进行封装,从而保证任意时刻只有一个节点真正执行定时任务,实现分布式环境下定时任务防重复执行。
1. 任务接口设计
框架定义了多个基于分布式锁的任务装饰器接口,业务侧只需要继承对应接口并实现 doRun() 方法,即可快速完成定时任务加锁执行:
// Redis 自动续期锁public interface AutoRenewalLockTaskRunner extends TaskRunner, Lockable { @Overridedefault void run(Map params) { RedisLockService.instance.autoRenewal().doInLock(key(), () -> doRun(params));}void doRun(Map 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 或具体资源维度进行区分,以便精确控制分布式锁粒度:
@Overridepublic String key() { return "schedule:lock:" getTaskName(); // 例如通过构造函数注入} 4. 异常处理
若获取分布式锁失败(例如锁已被其他节点占用),会抛出LockCreateException,当前任务会直接跳过执行,不会影响下一次调度触发。 也可以覆盖 handleException(LockException) 方法,自定义失败处理逻辑,例如记录日志、埋点监控或发送告警通知。 5. 集群效果
当所有节点使用相同的锁 key 时,最先获取锁的节点负责执行任务,其他节点会快速失败并退出,从而保证定时任务在分布式集群内始终以单节点方式运行,有效避免重复执行问题。
