You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel 5.5多Worker运行时Job Queue无法并行处理问题

Laravel 5.5 Database队列多Worker串行处理问题
  • 基于Laravel 5.5 + Database队列驱动,启动了5个Worker进程
  • 任务处理速率固定为每分钟100个,完全不受Worker数量影响
  • 本地测试验证:单个Worker必须完成当前任务后才会获取下一个任务,多Worker的并行优势完全失效
  • 此前自定义队列曾出现过同类问题,切换回默认队列后恢复并行,但当前所有任务都在默认队列中,仍存在串行问题

配置信息

ENV文件

QUEUE_DRIVER = database

Supervisord配置

[program:laravel_queue]
process_name=%(program_name)s_%(process_num)02d
command=php artisan queue:work --delay=10 --tries=10 --timeout=300
directory=/var/www/html
stdout_logfile=/var/www/html/storage/logs/laravel-queue.log
logfile_maxbytes=0
logfile_backups=0
redirect_stderr=true
autostart=true
numprocs=5
autorestart=true
startretries=86400

排查与解决思路

  1. 检查数据库锁机制兼容性
    Database队列依赖数据库行锁避免任务重复获取。Laravel 5.5的Database队列在MySQL 8.0+环境下使用FOR UPDATE SKIP LOCKED实现无等待取任务,而MySQL 5.7及以下只能用旧版SELECT ... FOR UPDATE,会导致Worker等待锁释放,表现为串行执行。
  • 升级MySQL到8.0+,或确认当前数据库是否支持SKIP LOCKED语法
  • 核对jobs表结构,确保reserved_at字段能正常更新
  1. 确认Worker进程数量
    执行ps aux | grep queue:work,检查是否真的有5个独立的Worker进程在运行。有时Supervisord的numprocs=5配置会因权限、路径问题未完全启动。

  2. 排查任务内部的全局锁
    如果任务代码中使用了全局锁(如Redis锁、文件锁),或任务间依赖共享资源并加了排他锁,会强制任务串行执行,和Worker数量无关。检查任务逻辑中是否存在Cache::lock('xxx')->get()这类全局锁代码。

  3. 调整Worker休眠参数
    默认情况下,队列无任务时Worker会休眠1秒,但如果任务持续存在,可通过--sleep=0强制Worker不休眠,立即轮询新任务:

php artisan queue:work --delay=10 --tries=10 --timeout=300 --sleep=0

注意:此操作会增加数据库查询频率,需根据服务器负载权衡。

  1. 检查任务锁释放情况
    如果任务执行超时或Worker异常退出,可能导致jobs表中reserved_at字段未被置空,任务被长期锁定。可通过SQL查询锁定任务:
SELECT * FROM jobs WHERE reserved_at IS NOT NULL;

对长期锁定的任务,可手动将reserved_at设为NULL,或执行php artisan queue:retry all重试。

  1. 确认队列名称一致性
    虽然使用默认队列,但需检查任务代码中是否误指定了其他队列,确保所有任务都通过dispatch((new Job)->onQueue('default'))或默认方式分发到default队列。

内容的提问来源于stack exchange,提问作者Yeo Bryan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 12:50:06