laravel高峰期cpu飙升八成因session仍用file驱动:gc并发扫描大量文件导致i/o阻塞;改用redis需清缓存、核对连接名与prefix、统一序列化配置;api路由默认无session,须手动加web中间件。

线上 Laravel 应用一到高峰期就 CPU 狂飙、响应变慢,八成是 Session 还在用 file 驱动扛着——这不是配置没改,而是改了没生效、连上了但读不到、或者连上了却卡在 GC 上。
Session CPU 飙高?先确认是不是 file 驱动在扫文件
别急着换 Redis,先看现象:PHP-FPM 慢日志里反复出现 FileSessionHandler::gc,storage/framework/sessions/ 目录下有几千甚至上万个文件,ls -1 | wc -l 超过 5000 就该警觉。这不是“可能有问题”,是已经出事了。
- file 驱动的 GC 默认每 100 次请求有 2 次概率触发,高并发下就是并发清理,I/O 阻塞直接拉满 CPU
- GC 不是删单个文件,是全量扫描目录+逐个
unlink(),文件数从 100 到 10000,耗时从毫秒级跳到秒级 - 哪怕你改了
SESSION_DRIVER=redis,如果没清缓存或配置冲突,照样走 file ——php artisan config:clear是必跑命令
Redis 驱动连得上但 session() 读不到?查 connection 和 prefix
写进去了、redis-cli keys laravel_session:* 能查到 key,但 session('user_id') 返回 null?大概率是 Laravel 写和读用了不同 Redis 连接或前缀。
-
config/session.php中的'connection'必须严格匹配config/database.php里redis.connections下的键名(比如'default'),拼错一个字母就 fallback 到 file -
'prefix'默认是laravel_session:,如果你在config/session.php里改过它,又没同步更新监控或清理脚本,就会读写错位 - 用
phpredis扩展时,低版本(如5.3.4以下)不兼容 Laravel 的序列化方式,现象是写进去是字符串,读出来是null;加'options' => ['serializer' => \Redis::SERIALIZER_PHP]强制统一
多应用共享登录状态?别用 Redis,选 database 驱动更稳
想让 App1 登录后跳 App2 还保持会话?Redis 看似快,但跨应用时容易因连接隔离、密码不一致、key 冲突导致 session 错乱。database 驱动反而更可控。
- 所有应用共用一张
sessions表,表结构由php artisan session:table生成,迁移时指定独立数据库连接(如--database=sessions_database) - 各应用的
config/session.php统一设'driver' => 'database'和'connection' => 'sessions_database',不依赖环境变量拼接 - 避免用 Redis 共享时常见的坑:不同应用用不同
prefix却连同一个实例、serialize配置不一致、密码通过REDIS_PASSWORD注入但 Laravel 并不自动读取它
API 路由里 session() 一直是 null?不是驱动问题,是中间件没挂上
Route::middleware('api') 下的控制器,session()->put() 看似执行成功,但下一请求就读不到——因为 api 中间件组默认不含 StartSession,session 根本没初始化。
-
web中间件组才包含\Illuminate\Session\Middleware\StartSession::class;api组为无状态设计,默认禁用 - 构造函数里调
session()必然为 null,因为中间件在控制器实例化之后才执行;必须在__invoke()或具体 action 方法里用 - 真要在 API 场景用 session(比如管理后台混合路由),手动加
->middleware('web'),但注意这会启用 CSRF 验证,需额外处理
最常被忽略的点:改完 SESSION_DRIVER 后,config:clear 只是第一步,还得确认 config/session.php 里没有硬编码 'driver' => 'file',以及 config/database.php 中 Redis 连接的 scheme 是否匹配(Docker 环境常用 redis://,本地开发常用 tcp://)。这些地方错一个,session 就静默退回到 file。











