PAYATHON 2026

ActiveJob 的 polynomially_longer 重试时间如何计算?

数据阿明

使用 wait: :polynomially_longer 时,等待时间随执行次数的四次方增长,并默认加入随机抖动,因此没有完全固定的时间表。默认的 attempts: 5 包含首次执行,最多安排 4 次重试。关闭抖动后,这四次等待依次为 3、18、83、258 秒。

polynomially_longer 需要显式指定;retry_on 默认的 wait 是 3 秒。默认参数和尝试次数的含义见 Rails retry_on 文档。

等待时间如何计算

原公式为:

((executions**4) + (Kernel.rand * (executions**4) * jitter)) + 2

以下假设任务持续触发同一条 retry_on 规则,且每次执行都失败。令 n 表示当前失败的执行次数:首次执行失败时,n = 1,计算的是第二次执行前的等待时间。

默认 jitter 为 0.15。不带参数的 Kernel.rand 返回大于等于 0、小于 1 的值,因此等待时间范围是:

n**4 + 2 <= wait < 1.15 * n**4 + 2

单位为秒。随机增量只作用于 n**4,不包括最后加上的 2。设置 jitter: 0 后,等待时间固定为 n**4 + 2。

5、10、20 次尝试的时间表

表中的等待时间是距离上一次失败的间隔,不是从任务首次启动算起的累计时间。默认抖动一列采用左闭右开区间,即包含下限、不包含上限。

第几次重试下一次是第几次执行jitter: 0,秒默认 jitter: 0.15,秒
123[3, 3.15)
2318[18, 20.40)
3483[83, 95.15)
45258[258, 296.40)
56627[627, 720.75)
671298[1298, 1492.40)
782403[2403, 2763.15)
894098[4098, 4712.40)
9106563[6563, 7547.15)
101110002[10002, 11502.00)
111214643[14643, 16839.15)
121320738[20738, 23848.40)
131428563[28563, 32847.15)
141538418[38418, 44180.40)
151650627[50627, 58220.75)
161765538[65538, 75368.40)
171883523[83523, 96051.15)
1819104978[104978, 120724.40)
1920130323[130323, 149871.15)

对应关系如下:

  • attempts: 5:使用前 4 行。
  • attempts: 10:使用前 9 行。
  • attempts: 20:使用全部 19 行。

如果任务始终失败,将这些等待间隔相加,可以得到最后一次执行前的累计等待时间:

attempts最多重试次数jitter: 0,累计秒数默认 jitter: 0.15,累计秒数
54362[362, 415.10)
10915351[15351, 17650.95)
2019562704[562704, 647103.90)

换算后,10 次尝试的累计等待约为 4.26 至 4.90 小时,20 次尝试约为 6.51 至 7.49 天。这些数值按公式计算,不包含任务执行耗时和队列调度延迟。

用 Ruby 生成其他次数的时间表

将 attempts 改为需要查看的总尝试次数即可。下面的代码计算等待范围,不执行任务,也不抽取随机数:

attempts = 20
jitter = 0.15

(1...attempts).each do |n|
  minimum = n**4 + 2
  upper_bound = minimum + n**4 * jitter

  printf(
    "Retry %2d -> execution %2d: %.2f <= wait < %.2f seconds\n",
    n, n + 1, minimum, upper_bound
  )
end

若需要固定间隔,可以在 retry_on 中显式设置 jitter: 0,再按 n**4 + 2 计算。

实际使用时要注意什么

attempts 限制的是这条 ActiveJob 重试规则的尝试次数。达到上限后,如果没有通过传入的代码块处理最终失败,异常会继续向底层队列系统传播。队列后端可能还有自己的重试机制,因此不能直接把表中的时间视为整个队列系统的最终执行时间表。Rails 文档说明了这一行为。

问题没有指定 Rails 版本,以上按所链接文档中的公式和默认参数计算。若项目修改了抖动配置,应使用实际生效的 jitter 重新计算。

备注:内容仅供参考。