laravel 10队列任务失败后不自动重试,需显式配置:最高优先级为任务类中$tries属性(如public $tries = 3),其次为retryuntil()方法或--tries命令行参数;退避时间默认非指数,须设$backoff数组或重写retryafter()实现动态延迟。

在 Laravel 10 中,队列任务失败后的重试行为不是默认无限循环的,而是由明确的配置控制:最大尝试次数决定任务何时被标记为“失败”,退避时间则影响每次重试之间的等待间隔。这两项设置共同构成容错与稳定性基础。
最大尝试次数的三种设置方式
你可以按优先级从高到低选择以下任一方式指定重试上限:
-
任务类内定义
$tries属性:适用于固定策略,如public $tries = 3;表示该任务最多执行 3 次(含首次) -
使用
retryUntil()方法动态计算截止时间:适合需要按时间而非次数控制的场景,例如dispatch(new ProcessOrder)->retryUntil(now()->addHour(2)); -
命令行启动时传参:运行
php artisan queue:work --tries=5,该值会覆盖任务类中定义的$tries,但不改变数据库中已入队任务的原始配置
退避时间的实现逻辑
退避不是简单地固定等待几秒,而是按重试次数逐步拉长延迟,避免瞬时重压。Laravel 默认采用指数退避(exponential backoff),但需手动启用或自定义:
- 若任务类中定义了
$backoff = 3;,首次失败后等 3 秒,第二次等 6 秒,第三次等 12 秒——即每次翻倍 - 更灵活的方式是重写
retryAfter()方法,返回具体秒数:public function retryAfter() { return now()->addSeconds(10 * pow(2, $this->attempts()))->getTimestamp() - now()->getTimestamp(); }
这样第 1 次重试延迟 10 秒,第 2 次 20 秒,第 3 次 40 秒 - 注意:
retryAfter()返回的是绝对时间戳差值(秒),不是 Carbon 对象;它仅对 Redis 和 Database 驱动生效,SQS 使用自身 DelaySeconds 机制
失败后如何干预与恢复
当任务达到最大尝试次数仍未成功,Laravel 会将其写入失败队列表(如 failed_jobs 表),并触发 JobFailed 事件。此时可:
- 用
php artisan queue:failed查看所有失败记录 - 执行
php artisan queue:retry [id]手动重试某条任务(重试时会重置 attempts 计数) - 调用
php artisan queue:forget [id]清除记录(仅移除,不执行) - 监听
JobFailed事件,在失败时发告警、记录日志或触发补偿逻辑
驱动差异对重试的影响
不同队列驱动对重试的支持程度不同:
-
Redis:支持精确延迟与即时重试调度,
retryAfter()效果最稳定 -
Database:依赖轮询
jobs表,重试时机受queue:work的轮询频率影响(默认每秒一次),可能有轻微延迟 -
SQS:不直接支持 Laravel 的
$backoff或retryAfter(),需通过DelaySeconds参数配合自定义逻辑模拟退避











