You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ShedLock:定时任务共用同一锁ID的执行逻辑及优化方案

问题解答

1. 凌晨1点时任务的执行行为

当runEveryMinute成功获取锁时,runOnceEveryNight会直接跳过本次执行,不会进入等待队列。这是ShedLock的默认行为:任务尝试获取锁失败时,不会阻塞等待,而是直接放弃当前周期的执行。

2. 针对需求的更优配置方案

你的核心需求是:允许runEveryMinute每晚跳过一次,但runOnceEveryNight必须执行(不能等待24小时重试),以下是几种可行方案:

方案1:给夜间任务添加锁等待时间

修改runOnceEveryNight的@SchedulerLock注解,增加waitForLock参数,让它在获取锁失败时等待一段时间,直到runEveryMinute的锁释放:

@Scheduled(cron = "0 0 1 * * *")
@SchedulerLock(
    name = "sameShedLockId",
    lockAtLeastFor = "PT10M",
    lockAtMostFor = "PT15M",
    waitForLock = "PT1M" // 最多等待1分钟获取锁
)
public void runOnceEveryNight() {
  // ... 原有业务逻辑
}

runEveryMinute的锁会在59秒后释放,runOnceEveryNight能在等待期内拿到锁执行;而runEveryMinute会因为锁被抢占跳过一次执行,完全符合你的需求。

方案2:调整分钟任务的定时规则,避开冲突时段

修改runEveryMinute的定时表达式,直接跳过凌晨1点整的执行,从根源上避免冲突:

// 每天0点-0点59分、2点-23点的每分钟第0秒执行,跳过1点整的时刻
@Scheduled(cron = "0 * 0,2-23 * * *")
@SchedulerLock(name = "sameShedLockId", lockAtLeastFor = "PT59S", lockAtMostFor = "PT59S")
public void runEveryMinute() {
  // ... 原有业务逻辑
}
方案3:在分钟任务中通过逻辑主动避开冲突

在runEveryMinute的方法内判断当前时间,若为凌晨1点整则直接返回,不执行业务逻辑:

@Scheduled("0 * * * * *")
@SchedulerLock(name = "sameShedLockId", lockAtLeastFor = "PT59S", lockAtMostFor = "PT59S")
public void runEveryMinute() {
  LocalTime now = LocalTime.now();
  // 凌晨1点整直接跳过执行
  if (now.equals(LocalTime.of(1, 0))) {
    return;
  }
  // ... 原有业务逻辑
}

内容的提问来源于stack exchange,提问作者Michiel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 04:35:39