必须用异步任务剥离耗时逻辑,否则高并发下会超时崩溃;安装think-queue后需配置redis驱动、定义带校验与手动删除的任务类、按场景选择push/later/直写zset投递方式,并用supervisor托管worker进程。

想让用户注册后立刻看到成功页面,而不是干等3秒发完邮件才响应;想上传Excel后马上跳转,而不是卡在“正在处理中”——这些场景必须靠异步任务把耗时逻辑彻底剥离出HTTP请求生命周期,否则高并发下Nginx超时、PHP-FPM进程池耗尽、用户体验崩盘全是分分钟的事。
安装与驱动配置
执行composer require topthink/think-queue安装扩展包,这一步不能跳过,否则后续所有操作都无效。
在config/queue.php中显式覆盖默认配置,尤其注意'default' => 'redis'——【sync驱动只适合本地调试,线上启用等于没异步】。
Redis连接参数必须完整填写:'host'、'port'、'password'、'select'一个都不能留空或沿用.env里未定义的占位符,否则消费者启动时直接报错退出,任务全积压在内存里不落地。
定义任务类
新建app/job/SendEmail.php,继承\think\queue\Job。
在fire方法开头就校验$data['to']格式,非法邮箱立即$job->fail()退出。
邮件发送逻辑完成后,必须手动调用$job->delete()。ThinkPHP不会自动清理已执行成功的任务,不删就会让Redis的List长度无限增长,最终触发ERR wrong number of arguments错误。
绝对不要在fire里写sleep(2)模拟延迟——这会锁死整个worker进程,同一时刻只能处理1个任务,吞吐量归零。
投递任务
方法一:即时执行用\think\Queue::push('app\job\SendEmail', $data, 'email'),适用于普通通知类任务。
方法二:延迟执行必须用\think\Queue::later(600, 'app\job\SendEmail', $data, 'email'),但要注意——【若服务器启用了NTP自动校时且发生时间回拨,ZSET中已到点的任务会被永久跳过】。
方法三:对顺序敏感的延迟任务(如订单超时关单),改用时间戳+自增序号拼接score:$score = time() . '.' . $seq,再通过$this->redis->zadd()直写,绕过think-queue默认的纯时间戳方案。
启动消费者守护进程
第一步:创建supervisor配置文件/etc/supervisor/conf.d/tp7-queue.conf,内容包含command=php /var/www/tp7/think queue:work --queue=email,default --sleep=3 --max-jobs=1000 --memory=128。
第二步:执行sudo supervisorctl reread && sudo supervisorctl update加载新配置。
第三步:执行sudo supervisorctl start tp7-queue:* 启动全部队列worker。
禁用--daemon参数——它会导致worker异常退出后无法自动重启,必须交由supervisor统一管理生命周期。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











