必须安装topthink/think-queue ^3.0扩展,配置config/queue.php中default为redis、connections.redis含正确host/port/select、failed设database并执行迁移;任务类继承think\queue\jobs\job,实现fire方法并调用$job->delete();推送用queue::push或later;消费者用php think queue:work --daemon --max-jobs=100。

ThinkPHP 6.x 自带的 think-queue 怎么装和配
直接用官方维护的 think-queue 扩展,别自己手写队列驱动。它封装了 Redis、Database、Sync(同步)、Beanstalkd 等多种驱动,且与 TP6 的容器、事件、命令行机制深度集成。
安装命令:composer require topthink/think-queue。装完后无需手动注册服务提供者——TP6 会自动加载。
配置文件在 config/queue.php,关键项包括:
-
'default' => 'redis':默认驱动,推荐设为redis(Database 驱动仅适合低频调试,性能差、无重试保障) -
'connections.redis' => [...]:确保'host'、'port'、'database'填对,Redis 连不上时任务会静默失败 -
'failed' => ['driver' => 'database']:失败任务存数据库,需先执行php think queue:table和php think migrate:run
如何定义一个可被队列执行的任务类
任务类必须实现 think\queue\Job 接口,但更推荐继承 think\queue\job 提供的基类 think\queue\Jobs\Job(注意命名空间是 think\queue\Jobs\Job,不是 think\queue\Job)。
最简结构:
namespace app\job;
use think\queue\Jobs\Job;
class SendEmailJob
{
public function fire(Job $job, $data)
{
// 实际业务逻辑,比如调用 Mail::send()
\think\facade\Mail::raw('Hello', function ($message) use ($data) {
$message->to($data['email']);
});
// 执行成功,手动删除该任务
$job->delete();
}
}
注意点:
- 不要在
fire()里 throw 异常来“失败重试”——框架靠返回值或抛出特定异常控制行为 - 想让任务失败后重试,就抛出
\think\exception\RetryException;想彻底失败并进 failed_jobs 表,就抛其他异常或不捕获 -
$job->attempts()可查当前重试次数,避免无限重试
怎么把任务推入队列、指定延迟、控制重试次数
推送靠 think\facade\Queue 门面,不是直接 new 类或调用静态方法。
常见推送方式:
- 立即执行:
Queue::push(new SendEmailJob(), ['email' => 'a@b.com']) - 延迟 60 秒:
Queue::later(60, new SendEmailJob(), ['email' => 'a@b.com']) - 指定连接(如用 database 驱动做测试):
Queue::connection('database')->push(...) - 限制最大重试次数(只对 Redis/Beanstalkd 有效):
Queue::push(new SendEmailJob(), [], ['maxTries' => 3])
注意:later() 在 Database 驱动下不可靠(依赖定时轮询),生产环境务必用 Redis。
消费者进程怎么起、怎么防崩、怎么热更新
运行命令:php think queue:work --daemon --sleep=3 --max-jobs=100
关键参数含义:
-
--daemon:启用守护模式(推荐),否则每执行一个任务就启一个新进程,开销大 -
--sleep=3:空闲时休眠 3 秒再查,太小加重 Redis 压力,太大响应延迟高 -
--max-jobs=100:每个进程最多处理 100 个任务后自动退出,防止内存泄漏累积 - 没加
--once就别在 supervisor 里配autorestart=true,否则会重复拉起多个 work 进程
热更新代码后,旧进程仍运行老代码——必须 kill 掉所有 queue:work 进程,再由 supervisor 重启。用 ps aux | grep 'queue:work' + kill -9 是最稳妥做法。
Redis 连接超时、任务死循环、未 catch 的异常,都会导致单个 worker 卡住不动。所以 --max-jobs 和 --timeout=60(超时秒数)必须配。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











