Laravel队列卡在pending状态主因是未启用真实驱动(如Redis)且配置未生效;需改QUEUE_CONNECTION、清缓存、用queue:work配合Supervisor常驻运行,并避免序列化大对象或连接未复用。
pending 状态不执行?绝大多数情况不是代码写错了,而是队列驱动没真正跑起来。Laravel 默认用 sync 驱动,它根本不会进队列,直接同步执行——这会让你误以为“队列在工作”,实际只是假象。
必须显式切换到真实驱动,比如 redis,并在 .env 中确认:
QUEUE_CONNECTION=redis REDIS_HOST=127.0.0.1 REDIS_PORT=6379
别漏掉 php artisan config:clear,Laravel 会缓存配置,改了 .env 不清缓存等于白改。
常见错误现象:
dispatch(new SendEmailJob()) 后,php artisan queue:work 没任何输出,数据库 jobs 表为空(说明根本没走数据库驱动)queues:default 列表,但 queue:work 进程启动后立刻退出或无响应(多半是 Redis 连接失败或权限问题)queue:work 进程的最小可行配置Supervisor 不是可选工具,是生产环境必须项。手动敲 php artisan queue:work 一旦终端断开或报错就停,任务直接积压。
关键点不在“怎么写配置”,而在“怎么验证它真在跑”:
command 必须带 --sleep=3 和 --max-jobs=1000,防止内存泄漏和无限重试拖垮进程autostart=true 和 autorestart=true 是基础,但必须加 startsecs=5,否则 Supervisor 可能误判进程启动失败/var/log/supervisor/laravel-queue.log,避免权限或路径解析问题一个精简但可用的 /etc/supervisor/conf.d/laravel-queue.conf:
[program:laravel-queue] process_name=%(program_name)s_%(process_num)02d command=php /var/www/myapp/artisan queue:work redis --sleep=3 --max-jobs=1000 --max-time=3600 autostart=true autorestart=true startsecs=5 user=www-data numprocs=2 redirect_stderr=true stdout_logfile=/var/log/supervisor/laravel-queue.log
配完别忘了: supervisorctl reread && supervisorctl update && 
queue:work 和 queue:listen 到底该用哪个?答案很明确:只用 queue:work,彻底忘掉 queue:listen。
queue:listen 是 Laravel 5.2 之前的遗留命令,它靠轮询 + include 重新加载代码,每次任务都重新启动整个 Laravel 应用上下文,内存占用高、启动慢、热更新不可靠,官方早已弃用。
queue:work 是常驻进程,复用应用实例,性能好得多,但代价是——代码变更后必须重启进程才能生效。这就是为什么 Supervisor 的 autorestart 要配合部署脚本使用:
supervisorctl restart laravel-queue:*
php artisan queue:restart 触发优雅重启(它只是往 Redis 写个信号,queue:work 进程自己监听并退出)别指望修改了 Job 类就自动生效,不重启进程,旧代码一直跑着。
不是 Redis 不行,而是 Laravel 默认配置太“保守”。延迟高往往卡在连接池或序列化环节:
redis 连接配置里没开 pconnect(持久连接),每次取任务都新建 TCP 连接,耗时翻倍。在 config/database.php 的 redis 部分加 'options' => ['prefix' => 'laravel_database_'] 不够,要确认 Redis 扩展支持 phpredis 并启用 pconnect
Request 实例)作为构造参数,序列化成 JSON 后体积暴涨,Redis 读写变慢。应只传 ID 或必要字段,用 __construct($userId) 而非 __construct(Request $request)
--max-time=3600,单个任务超时后被强制 kill,Supervisor 立刻拉起新进程,反复 fork 导致系统负载飙升,间接拖慢其他任务验证是否真卡 Redis:在 queue:work 命令后加 --verbose,看每条日志的时间戳间隔。如果“popping”和“processing”之间差几百毫秒,基本就是连接或序列化问题。