laravel队列任务默认不重试,需显式配置$tries或--tries参数指定最大重试次数;重试等待时间由$backoff数组或retryuntil()控制;已失败任务需手动php artisan queue:retry重试。

Laravel 队列任务失败后**默认不重试**,必须显式配置才能触发重试行为。关键不在“开启开关”,而在于明确指定重试次数和时机——没设 $tries 或没传 --tries,就是执行一次失败即进 failed_jobs 表。
设置最大重试次数
重试的前提是定义“最多试几次”。Laravel 提供两种等效但优先级不同的方式:
- 在任务类中声明 public $tries = 3;(含首次执行,即总共运行最多 3 次)
- 启动 worker 时加参数:php artisan queue:work --tries=3
- 若两者都设,任务类里的 $tries 会覆盖命令行参数
- 两者都没设 → 失败后不重试,直接落库
控制重试等待时间
单纯设 $tries 只决定“试几次”,不控制“隔多久再试”。延迟靠 $backoff 或 retryUntil:
- $backoff = [1, 5, 60]; 表示第 1 次失败后等 1 秒、第 2 次等 5 秒、第 3 次等 60 秒;数组不够长时,后续失败复用最后一个值
- retryUntil() 设绝对截止时间,例如 $this->retryUntil(now()->addMinutes(10));,适合依赖外部服务恢复的场景
- $tries 和 retryUntil() 互斥:只要定义了 $tries,retryUntil 就被忽略
手动重试失败任务
自动重试只适用于未耗尽尝试次数前的失败。对已进入 failed_jobs 表的任务,需人工干预:
- 查失败记录:php artisan queue:failed
- 重试单个:php artisan queue:retry 123(123 是 failed_jobs.id)
- 重试全部:php artisan queue:retry all(慎用,可能引发重复操作)
- 若用 Redis 等非默认连接,需加 --queue=redis
避免重试失效的常见坑
重试失败不一定是逻辑问题,常因底层数据损坏或环境缺失导致:
- 检查 failed_jobs.payload 字段是否被截断(尤其用 MySQL TEXT 类型时),否则 unserialize() 会报错 “Error at offset”
- 任务中避免引用不可序列化的对象,如 $request、$_SERVER、cURL handler、闭包
- 不要在 handle() 中写 dd()、exit 或 die,会导致 worker 进程崩溃,阻塞后续任务
- 高优或时效敏感任务建议单独使用专用队列(如 --queue=critical),并独立监听,避免被低优任务拖慢











