ThinkPHP6定时任务本身不支持定时重试,需通过队列任务实现:在定时器中推送任务,由任务类的$maxTries和$retryAfter控制重试次数与间隔,未捕获异常触发重试,数据库驱动自动记录attempts字段。

ThinkPHP6 定时任务本身不直接提供“定时重试”能力,真正需要重试的是队列任务(比如由定时器触发后推入队列的异步任务)。所谓“定时任务失败重试”,本质是:在定时执行逻辑中调用队列任务,并依靠队列系统的重试机制保障可靠性。关键不在“定时器”,而在“队列任务类”的配置与异常处理。
确保任务类正确声明重试参数
重试行为由任务类自身控制,不是全局配置。必须在任务类中显式定义两个 public 属性:
- public $maxTries = 3;:表示该任务最多尝试执行 3 次(含首次),超过即进 failed_jobs 表
- public $retryAfter = 60;:表示每次失败后,等待 60 秒再重新入队(单位为秒)
注意:不能写成 protected 或 private;不能在 config/queue.php 里配 maxTries,框架完全不读这个字段;命令行启动时若加了 --tries=1,会强制覆盖类中设置。
让失败真正触发重试
只有未被捕获的异常才能激活重试流程。常见错误是把异常吞掉了:
- ❌ 错误写法:在 handle() 或 fire() 方法里用 try/catch 捕获所有异常后 return 或静默忽略
- ✅ 正确做法:只捕获可预期、可恢复的异常(如网络超时),其他异常直接抛出;或 catch 后重新 throw
- 数据库驱动下,failed_jobs 表的 attempts 字段会自动递增,可用于验证是否真的重试了
配合定时器合理触发任务
使用 think-swoole 的定时器、或者 Linux crontab 调用 php think schedule:run,都可以触发队列投递。例如:
- 在定时器中执行
Queue::push(new OrderCancelJob($orderId)) - 不要在定时器里直接执行耗时逻辑,而是交给队列异步处理,这样重试才可控
- 如果定时器本身失败(如进程崩溃),需靠外部监控补救;队列任务的重试则由 queue:work/listen 进程保障
生产环境建议增强容错
单纯依赖 maxTries 不够,建议叠加以下实践:
- 在任务数据中嵌入 retry_count 字段,业务层判断是否达到上限,避免无意义重试
- 对 Redis 驱动,启用
'failed' => ['type' => 'redis']提升失败任务读写性能 - 配合日志 +
php think queue:failed-show ID快速定位失败原因 - 高并发场景下,用 Supervisor 或 Swoole 协程启动多个消费者,防止单点阻塞影响重试时效
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











