php会话垃圾回收依赖概率触发与过期阈值协同工作,仅设session.gc_maxlifetime不足以保障及时清理,须同步配置gc_probability和gc_divisor;其值不控制cookie过期或外部存储过期逻辑。

PHP会话垃圾回收不是“设个时间就自动删”,它靠概率触发 + 过期阈值判断协同工作,只调 session.gc_maxlifetime 不足以保证清理及时,必须同步调整 session.gc_probability 和 session.gc_divisor。
为什么 session.gc_maxlifetime 不等于 Session 实际有效期
session.gc_maxlifetime 仅在 GC 扫描时起作用:它定义的是“最后访问时间早于当前时间减去该值”的 session 文件才被判定为可删除。它不控制 Cookie 过期、不控制 session_start() 是否接受旧 session、也不影响 Redis 等外部存储——那些得靠你自己实现过期逻辑。
- 设为
1800(30 分钟),不代表 30 分钟后 session 立刻失效;只要没触发 GC,过期文件仍躺在磁盘上 - 用户持续刷新页面,
$_SESSION里数据能一直续命,但 GC 不扫,旧文件不会被物理删除 - 使用
session.save_handler = redis时,gc_maxlifetime完全无效,Redis 的 key 过期必须靠SET ... EX或服务端定时任务
session.gc_probability / gc_divisor 怎么配才合理
每次执行 session_start() 时,PHP 以 gc_probability / gc_divisor 的概率启动 GC 扫描。这个概率直接决定清理频率和 I/O 压力。
- 默认
gc_probability=1、gc_divisor=100→ 每 100 次请求约触发 1 次 GC,适合小流量站 - 中等流量生产环境建议
gc_probability=1、gc_divisor=1000→ 降低扫描频次,减少阻塞风险 - 高并发集群或使用负载均衡时,
gc_probability=0更稳妥,避免多节点重复扫描或漏扫;改用cron脚本统一清理:find /var/lib/php/sessions -name "sess_*" -mtime +1 -delete - 切勿设
gc_probability=100、gc_divisor=100→ 每次请求都扫,I/O 成瓶颈,响应直线上升
多站点共用 PHP-FPM 时的常见坑
GC 扫描是按 session.save_path 目录进行的,不区分域名或应用。如果多个站点共享默认 /var/lib/php/sessions,一个站的 GC 可能误删另一个站的 session 文件。
- 必须为每个站点设置独立路径:
session_save_path('/var/lib/php/sessions/site-a')或在 php.ini 中配session.save_path = "/var/lib/php/sessions/%n"(配合session.name隔离) - 不能只靠修改
gc_probability来“加速清理”——这只会让误删更频繁 - 若用数据库存 session,GC 机制完全不生效,必须在登录/登出逻辑里显式更新
expires_at字段,并配定时 SQL 清理:DELETE FROM sessions WHERE expires_at
最易被忽略的一点:GC 是被动触发的,且只清理「已过期」的 session;它不会因用户主动登出、浏览器关闭而立刻释放资源。真正可控的清理动作,始终要落在业务代码里——比如登出时调用 session_destroy() 并 unset cookie,而不是指望 GC 某天扫到它。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











