在任务调度系统中,一个常见的问题是任务在触发时如果发现任务队列已满,会被改期到一分钟后执行。然而,这种改期行为会导致任务执行的节奏发生永久性偏移。具体来说,当任务被改期后,后续的执行时间都是基于改期后的时间来计算的,而不是按照原先的节奏。这种现象在任务调度系统中被称为“计划永久偏移”。

现象描述

当一个任务在触发瞬间发现任务队列已满时,系统会将该任务的执行时间改期到一分钟后。虽然任务最终会在改期后的时间执行,但由于执行时间是基于改期后的时间来计算的,这会导致任务执行的节奏发生永久性偏移。换句话说,任务的执行时间不再是按照原先的计划来执行,而是每次都向后推迟一分钟。

原因分析

这种现象的原因在于任务调度系统中的“Busy”分支执行了一个更新操作:UPDATE schedules SET next_run_at = now + BUSY_RETRY_MS。这个操作将任务的下次执行时间改期到了当前时间加上一个固定的延迟(BUSY_RETRY_MS)。当任务调度器在下一次运行时,它会读取这个更新后的时间作为任务的due时间,然后通过following()函数继续推算后续的执行时间。此外,任务的request_key中包含了更新后的due时间,这意味着在重试时,系统会使用一个新的任务键(key)来处理任务。

复现步骤

为了更好地理解这个问题,我们可以通过以下步骤来复现这一现象:

  1. 计划任务:设置一个任务,首次执行时间为10:00,每隔60分钟执行一次。
  2. 队列满的情况:在10:00时,如果任务队列已满,系统会将任务的执行时间改期到10:01。
  3. 实际执行:任务会在10:01执行。
  4. 后续执行:之后依次是11:01、12:01,且每次队列满时都会再次叠加偏移。

通过以上步骤,我们可以看到任务执行的节奏发生了永久性偏移,每次执行时间都向后推迟一分钟。这种现象在任务调度系统中可能会导致任务执行的不一致性和不可预测性,因此需要引起重视并加以解决。