ThinkPHP 使用 Redis 队列需满足两点:安装 topthink/think-queue 包且配置 default 为 'redis',否则默认走 sync 同步模式;同时确保 PHP 已启用 redis 扩展、Redis 服务正常运行且连接参数(password、select)与实际一致。

ThinkPHP 使用 Redis 队列,核心就两点:装对包、配对参数。没装 topthink/think-queue 或者 default 没设成 redis,队列默认走 sync 同步模式——你根本没在用队列。
确认 PHP 环境已支持 Redis
这是前置硬条件,跳过直接报错。不是“装了 Redis 服务”就行,PHP 进程必须能连上它。
- 运行
php -m | grep redis,输出里要有redis;没有就去装 phpredis 扩展(不是 predis) - 检查 Redis 服务是否真在跑:
redis-cli ping返回PONG才算通 - 如果 Redis 有密码或非默认库(比如
select => 1),password和select必须和实际一致,填错会导致连接成功但任务写不进队列
config/queue.php 的关键字段不能错
ThinkPHP 6+ 统一走 config/queue.php,TP5 是 application/extra/queue.php。文件路径错、键名拼错、类型写成字符串都会静默失效。
-
default必须是'redis'(小写),不是'Redis'也不是'REDIS' -
connections.redis.type也得是'redis',漏写或写成'redis-driver'会 fallback 到 sync -
queue参数决定 Redis List 的 key 名,默认是'default',消费时命令要匹配:php think queue:listen --queue=default -
retry_after和expire要区分清楚:retry_after是任务被取出后多久没 delete 就自动放回队列重试;expire是任务在队列里最长存活时间(单位秒),超时会被丢弃
任务类 fire 方法里必须手动 delete 或 release
ThinkPHP 的队列不会自动清理任务。fire 执行完不调 $job->delete(),这个任务就永远卡在队列里,下次监听还会捞出来执行一遍。
立即学习“PHP免费学习笔记(深入)”;
- 成功逻辑结尾加
$job->delete(),别忘了 - 失败时用
$job->release(10)延迟重试,别直接 return;否则任务就丢了,且不会进 failed 表(除非你配了failed.type => 'database') -
$job->attempts()返回当前重试次数,建议用它控制最大重试阈值,避免无限循环失败 - 别在 fire 里 throw 未捕获异常——它会让 worker 进程崩溃退出,而不是触发 release
启动监听前先验证队列是否真在写入
很多人配完就跑 php think queue:listen,发现没反应,其实是任务压根没进 Redis。最简单的验证方式是手动 push 一个测试任务:
php artisan tinker
> \think\facade\Queue::push('app\job\TestJob', ['msg' => 'test']);
然后进 Redis 查:redis-cli lrange default 0 -1,能看到 JSON 字符串才算真正打通。如果返回空,问题一定出在配置或 push 调用位置(比如控制器里没 use Queue facade)。
另外注意:生产环境别用 queue:listen,它单进程、无守护、崩了不自启;换成 queue:work --daemon 或配合 supervisor 管理进程。



















