要让thinkphp6稳定支撑1万并发异步任务,需分层解耦、合理选型(redis用于轻量场景,rabbitmq用于核心链路)、常驻协程化消费、任务投递轻量化、加原子锁防超卖、启用失败队列与监控。

要让 ThinkPHP6 稳定支撑 1 万并发异步任务,不能只靠“加队列”就完事——核心在于分层解耦 + 合理选型 + 常驻消费 + 容错加固。Redis 适合扛量但不保可靠,RabbitMQ 保可靠但需精细配置;单纯用 php think queue:listen 进程模型扛不住万级并发,必须升级为常驻、协程化或进程池方案。
选对队列后端:中小规模用 Redis,核心链路用 RabbitMQ
Redis 轻快,适合日志归档、短信通知、非关键推送等场景;RabbitMQ 提供持久化、ACK、死信、优先级,适合订单确认、库存扣减、支付回调等不可丢、不可重的流程。
- Redis 配置(
config/queue.php)确保启用连接复用与前缀隔离:
'redis' => [
'type' => 'redis',
'host' => '127.0.0.1',
'port' => 6379,
'password' => '',
'select' => 1,
'prefix' => 'tp6:queue:',
'persistent' => true,
'timeout' => 2
] - RabbitMQ 必须手动集成
php-amqplib,禁用 think-queue 的薄封装:
composer require php-amqplib/php-amqplib
消费者脚本独立部署,开启basic_qos(10)限流、delivery_mode=2持久化、手动basic_ack,避免消息堆积或重复。
任务投递要轻量:避免在请求中做重操作
控制器里只负责“发指令”,不构造数据、不查库、不序列化大对象。把组装逻辑下沉到任务类的 __construct() 或 fire() 开头,用 ID 替代完整模型实例。
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
- 正确写法(仅传 ID):
Queue::push(new OrderConfirmedJob($orderId)); - 错误写法(序列化整个 Order 对象):
Queue::push(new OrderConfirmedJob(Order::find($orderId))); // 内存爆炸风险 - 秒杀类任务额外加 Redis 原子锁:
if (Redis::set('stock_lock:'.$skuId, 1, ['nx', 'ex' => 5]) === false) { throw new Exception('抢购太火爆,请重试'); }
消费者必须常驻且可伸缩
CLI 监听器(php think queue:listen)是单进程、无超时控制、无并发限制的“玩具模式”,万级并发下会迅速成为瓶颈。应切换为:
-
Swoole 协程消费者(推荐):利用
Swoole\Coroutine\Redis+brpop阻塞监听,单进程轻松支撑数千 QPS:
go(function () {
$redis = new \Swoole\Coroutine\Redis();
$redis->connect('127.0.0.1', 6379);
while (true) {
$res = $redis->brpop(['tp6:queue:default'], 5);
if ($res) { dispatchJob(json_decode($res[1], true)); }
}
}); -
Supervisor 管理多 worker 进程:启动 8–16 个
php think queue:work --queue=default --sleep=1 --max-jobs=500实例,配合--daemon模式减少启动开销。
失败与监控不能少
没有重试策略和失败记录,万级任务等于万级盲区。必须启用失败队列并接入日志追踪:
- 在
config/queue.php中配置失败存储:
'failed' => [
'type' => 'database',
'table' => 'failed_jobs',
'connection' => null,
],
并执行迁移:php think migrate:create CreateFailedJobsTable - 每个任务类内强制实现重试逻辑:
public function fire(Job $job, $data) {
if (!$this->sendEmail($data)) {
if ($job->attempts() $job->release(60); // 60秒后重试
} else {
$job->delete();
}
} else {
$job->delete();
}
} - 用 Prometheus + Grafana 监控队列长度、消费延迟、失败率(通过 Redis
llen tp6:queue:default和自定义埋点)。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!










