
ThinkPHP异步任务队列不是装完扩展就能自动跑起来的,关键在配置驱动、启动方式和失败处理三处。默认是 sync 驱动,任务当场同步执行,根本没进队列——这是绝大多数人踩坑的起点。
必须改掉的默认配置
打开 config/queue.php,重点检查并修改以下几项:
- 'default' => 'redis'(不能留'sync')
- 在 connections.redis 下显式写全连接参数:'host'、'port'、'password'、'database'(注意:不是'select',ThinkPHP 8.1+ 已废弃该字段)
- 'retry_after' => 120(设为任务预估最长耗时 × 1.5,比如发邮件含附件要 80 秒,这里至少填 120)
Redis 驱动要防静默退化
如果漏配 host/port/database,think-queue 不会报错,而是悄悄 fallback 回 sync 驱动——你 push 了任务,页面返回成功,但日志没输出、数据库没更新,实际什么都没异步发生。
验证是否真异步:在任务 fire() 里加 sleep(5),再刷新页面看响应时间。如果仍是秒回,说明还在 sync;如果卡住 5 秒,那才是“假异步”(即同步执行),还没切到 Redis。
立即学习“PHP免费学习笔记(深入)”;
失败任务不能靠默认记录
Redis 驱动默认不保存任何失败信息,任务崩了你也看不到。Database 驱动会自动建 failed_jobs 表并写入,但 Redis 不会。
- 方案一:监听 JobFailed 事件,在回调里手动记日志或入库
- 方案二:启动消费者时加参数:php think queue:work redis --tries=3 --delay=60,让框架自动重试并延后,但错误堆栈仍不保留
- 别用 php think queue:failed 查 Redis 失败任务——它只对 database 驱动有效
守护进程别用 --daemon
php think queue:work --daemon 看似省事,实则危险:PHP CLI 进程长期运行会累积内存泄漏,几小时后可能 OOM。生产环境必须用 supervisor 或 systemd 管理 worker,每次执行完自动重启,释放内存。
推荐 supervisor 配置片段:
[program:tp-queue]
command=php /var/www/your-app/think queue:work redis --sleep=3 --max-jobs=100
autostart=true
autorestart=true
user=www-data
redirect_stderr=true
stdout_logfile=/var/log/tp-queue.log



















