高并发下laravel吞吐量低的主因是连接层、缓存层和任务调度层资源争用或未复用;需启用redis持久连接、配置mysql连接池、选用合适队列驱动并异步化日志。

高并发下 Laravel 吞吐量上不去,问题通常不出在业务代码本身,而是连接层、缓存层和任务调度层的资源争用或未复用。直接改逻辑不如先堵住这三处漏点。
redis 缓存连接频繁重建导致 timeout
当 php artisan queue:work 或高频 API 请求密集调用 Cache::get() 时,若 Redis 连接未复用,每个请求都新建 TCP 连接,很快触发 Connection refused 或 read error on connection 错误。
- 确认已启用
phpredis扩展(php -m | grep redis),禁用predis(二者不可混用) - 在
config/database.php的redis.default配置中显式添加'persistent' => true -
.env中必须设为REDIS_CLIENT=phpredis,否则 Laravel 仍走 Predis 分支 - 搭配
CACHE_DRIVER=redis使用,array或file驱动无法支撑并发读写
database 连接池缺失引发 MySQL Too many connections
默认 Laravel 使用短连接,FPM 每次请求结束即断开 DB 连接,高并发时连接数飙升,MySQL 报错 Too many connections,但实际空闲连接并未释放复用。
- 仅当使用 Swoole / RoadRunner 等常驻进程时,才可开启 PDO 连接池;FPM 下无效
- 在
config/database.php的mysql配置块中添加'pool'子项(Laravel 10+ 支持) -
'min_connections'建议设为 CPU 核心数 × 2,'max_connections'不超过 MySQL 的max_connections值的 70% - 务必配合
DB_PERSISTENT=true环境变量(部分驱动需手动启用持久化)
queue:work 并发 worker 数量与队列驱动不匹配
启动了 8 个 queue:work 进程,但底层用的是 database 驱动,结果所有 worker 争抢同一张 jobs 表,出现大量锁等待,吞吐反而下降。
-
database驱动本质是轮询 + 行锁,worker 数建议 ≤ 3;再多只会增加竞争 - 生产环境必须切换至
redis或sqs驱动,才能真正支持横向扩展 - Supervisor 配置中
numprocs=4是并发上限,但需确保 Redis 实例能承载对应 QPS - 每个 worker 加上
--timeout=90和--max-jobs=500,防止单个长任务阻塞整个进程
日志写入阻塞主线程且未分级
线上环境还用 single 日志驱动,每条请求都同步写磁盘,flock() 锁导致请求排队,ab -n 1000 -c 100 测试时 TTFB 直接翻倍。
- 生产环境必须禁用
single和daily,改用stderr+queue驱动组合 - 在
config/logging.php中为stackchannel 设置'driver' => 'daily'仅用于本地,生产用'driver' => 'errorlog' - 关键错误(如 DB 异常、认证失败)可单独走
papertrail或slack驱动,避免污染主日志流 - 不要在
AppServiceProvider中动态修改日志级别——它会在每次请求初始化,开销不可忽视
真正卡吞吐的从来不是“写了多少行代码”,而是连接没复用、锁没分散、日志没异步。这些点不处理,加机器只是把瓶颈从 PHP 层转移到 MySQL 或 Redis 层。











