ThinkPHP 高并发下 Session 文件锁可导致请求阻塞,实测中第二个并发请求需等待第一个请求完全执行完成,甚至触发"Fatal error: Maximum execution time of 30 seconds exceeded in thinkphp\library\think\Session.php on line 534"错误。
原因分析
PHP 默认会话处理器为 session.save_handler = files,当调用 session_start() 时会取得文件独占锁(flock),只有在该请求处理结束后才会释放。根据 2025 年 10 月 25 日的技术资料,同一用户的多个并发请求会因 Session 文件被锁定而串行执行,即使请求逻辑互不相关。ThinkPHP 默认 file 驱动在高并发下因磁盘 I/O 和文件锁争抢,常见现象是 session_start() 卡住、响应变慢甚至返回 504 错误(2026 年 4 月 10 日资料)。
解决方案一:使用 session_write_close() 提前释放锁
在操作完 Session 后立即调用 session_write_close() 保存数据并释放文件锁。代码示例:
session_start(); $_SESSION["count"]=1; session_write_close(); // 释放锁 sleep(10); // 后续逻辑不再阻塞其他请求
根据 2021 年 3 月 10 日的测试反馈,不加入 session_write_close() 时并发 3 个进程访问该页面,第一个执行 10 秒、第二个 20 秒、第三个 30 秒;加入后 3 个进程会同时在 10 秒后执行完成。注意调用该方法后当前脚本不能再对$_SESSION 进行写操作(2025 年 6 月 9 日资料)。
解决方案二:切换至 Redis 存储驱动
在 php.ini 中配置:
session.save_handler = redis session.save_path = "tcp://127.0.0.1:6379?timeout=2&retry_interval=10" session.gc_maxlifetime = 1440
Redis 键名标准格式为'PHPREDIS_SESSION:' . $sessionId(2026 年 4 月 21 日发布)。Redis 不仅内存读写快,还天然支持原子操作和过期自动清理。需注意启用 phpredis 扩展,并检查 Cookie 传递及超时设置(2026 年 4 月 10 日资料)。
解决方案三:自定义 Session 处理器
通过 session_set_save_handler() 注册自定义 Redis 处理器,提供完全控制权。需实现 open、close、read、write、destroy、gc 六个必需方法。在 write 方法中执行$redis->set($id, $data) 并立即调用$redis->expire($id, $this->sessionExpireTime)(2026 年 4 月 21 日资料)。该方法适用于需适配旧版 PHP、多 Redis 实例或带认证的生产环境。
注意事项
1. PHP 7 中可设置 session_start(['read_and_close' => true]) 在读取会话数据后立即关闭会话释放锁(2025 年 6 月 9 日资料)。2. Redis 的 session 处理器默认没有锁功能,而 Memcached 默认启用锁功能,可通过设置 memcached.sess_locking = off 关闭(2025 年 6 月 9 日资料)。3. session.gc_maxlifetime 默认值为 1440 秒(24 分钟),需根据业务调整(2025 年 10 月 15 日资料)。4. 开启 app_debug => true 会让框架每请求都重新解析路由、检查模板、记录日志,性能直接打五折,上线后务必设 APP_DEBUG=false(截至 2026 年 3 月 10 日)。
参考来源
来源:CSDN 博客 - PHP 方法锁阻塞,session_start() 卡死、session 锁定导致并发阻塞 解决办法
来源:技术社区 - 高并发场景下的 PHP Session 优化:Redis 存储实战与性能对比数据(2025 年 10 月 25 日)
来源:技术社区 - ThinkPHP 如何实现高性能的 Session 存储_将 Session 切换至 Redis 驱动(2026 年 4 月 10 日)
来源:技术社区 - PHP 会话优化:Redis 存储 Session 替代文件锁的并发方案(2026 年 4 月 21 日发布)
原文链接:https://www.zjcp.cc/ask/9576.html
