retryafter() 优先级高于 $backoff,redis 驱动下只要定义了 retryafter() 就完全覆盖 $backoff;database 驱动不支持 retryafter(),仅依赖 $backoff。retryafter() 返回从当前失败时刻起算的绝对延迟秒数,且每次失败后重新调用,可动态计算。

retryAfter() 方法只在 Redis 驱动下生效,且会完全覆盖 $backoff 属性——哪怕你写了 $backoff = [1, 3, 5],只要定义了 retryAfter(),它就不起作用。
retryAfter() 和 $backoff 到底谁管用?
两者语义不同,不能混用:前者是每次重试的「绝对延迟秒数」(从当前失败时刻起算),后者是「相对间隔数组」,仅用于 database / redis 驱动,且只在 $tries > 1 时参与调度。
-
retryAfter()必须返回整数,例如return 2;表示失败后 2 秒重试 -
$backoff = [1, 3, 5]表示第 1 次失败后等 1 秒、第 2 次等 3 秒、第 3 次等 5 秒 - Redis 驱动中,
retryAfter()优先级高于$backoff,一旦存在,$backoff彻底失效 - database 驱动不支持
retryAfter(),只认$backoff(Laravel 9+ 起部分版本支持,但行为不稳定,不建议依赖)
为什么 retryAfter() 返回值每次都重新计算?
因为 Laravel 在每次任务失败后,都会重新实例化 Job 类并调用 retryAfter(),所以你可以动态返回不同值,比如根据错误类型或重试次数调整延迟:
public function retryAfter()
{
if ($this->attempts() <code>return $this->attempts() * 5;</code>
}
这比静态 $backoff 更灵活,但要注意:每次调用都是一次 PHP 方法执行,虽性能影响可忽略,但若逻辑复杂(如查数据库、调 API),反而拖慢重试调度。
Redis 延迟重试不准?检查这几个点
Redis 驱动支持亚秒级延迟(毫秒),但实际精度受 worker 启动参数和 Redis 版本限制:
- 确保队列驱动确实是
redis,不是sync或database—— 后两者不支持毫秒级 delay - worker 必须加
--sleep=0,否则默认每秒轮询一次,会丢失 - 确认 Redis 服务器时间与 PHP 进程时间一致(时钟漂移会导致 ZSET 排序错乱)
- Laravel 10+ 才完整支持
delay(now()->addMilliseconds(100));旧版本只向下取整到秒
retryAfter() 和 retryUntil() 能一起用吗?
不能。二者逻辑冲突:retryAfter() 控制「每次重试等多久」,retryUntil() 控制「最多重试到什么时候」。Laravel 只认其中一个:
- 如果任务类定义了
retryAfter(),retryUntil()将被忽略 - 如果没定义
retryAfter(),但handle()中调用了$this->retryUntil(...),则按截止时间判断是否继续重试 - 命令行参数
--tries和$tries属性仍生效,但它们控制的是「总次数上限」,不干涉延迟逻辑
真正容易被忽略的是:retryAfter() 的返回值是「从当前失败时刻起算的秒数」,不是从首次分发起算,也不是累计值。如果你需要基于首次分发时间做退避(比如指数退避 + 截止时间),得自己在 failed() 里手动 dispatch 并算好 delay()。











