ThinkPHP6.0异步任务执行流程分发核心是剥离业务逻辑交由独立进程消费:第一步确认队列驱动非sync且Redis select指定非0库;第二步定义含fire方法的任务类,只传轻量数据;第三步控制器中用Queue::push轻量投递;第四步用supervisor管理php think queue:listen监听,禁用--daemon。

ThinkPHP6.0异步任务执行流程的分发,核心在于把业务逻辑从HTTP请求线程中剥离出来,交由独立进程消费——不是“写完就完”,而是“推得准、接得住、不丢不重”。
第一步:确认队列驱动已启用且非sync
打开config/queue.php,检查'default'值是否为'redis'或'database',绝不能是'sync';若为'sync',所有任务仍在当前请求中同步执行,根本不算异步。
检查connections.redis块中'host'、'port'、'select'是否与实际Redis服务匹配,【select必须指定非0库,避免与缓存共用db0导致KEY冲突】。
第二步:定义可投递的任务类
运行命令生成任务类:php think make:job SendSmsJob。
立即学习“PHP免费学习笔记(深入)”;
在生成的app/job/SendSmsJob.php中,必须实现fire(Job $job, $data)方法,且内部不能直接调用exit、die或未捕获的throw——否则消费者进程会异常退出。
任务构造时只传ID或轻量数组,禁止传new User()等完整模型实例,否则序列化体积膨胀、反序列化失败率陡增。
第三步:控制器内完成轻量投递
在控制器方法中,调用Queue::push(new SendSmsJob($data)),其中$data应只含手机号、模板ID、参数数组三类字段。
这一步操作起来很简单,直接把文件拖进去就行。但注意:不能在fire()里查库拼数据,必须在投递前组装好;否则每台消费者都要重复查一次DB,万级并发下DB瞬间被打穿。
若需延迟执行,用Queue::later(300, new SendSmsJob($data)),但要警惕Redis ZSET score精度问题——系统时间回拨会导致任务永远不触发。
第四步:启动消费者监听指定队列
在服务器上执行:php think queue:listen --queue=default --delay=60 --memory=128 --tries=3。
【--queue参数不可省略,否则默认监听所有队列,多业务混杂极易互相干扰】。
不要用--daemon模式,它在PHP-FPM环境下存在内存泄漏风险;改用supervisor管理进程,配置autorestart=true和startsecs=5确保崩溃后自动拉起。
每个应用节点都运行相同命令,它们会从同一个Redis队列中争抢任务,Redis的RPOP原子性天然保证一个任务仅被一台机器消费。



















