PHP 8.1 默认不自动压缩会话数据,需通过自定义 session_set_save_handler 在 write/read 阶段手动 gzencode/gzdecode,或改用 Redis 并按需压缩大字段;php_serialize 等 handler 仅改序列化格式,不压缩。

PHP 8.1 默认不自动压缩会话数据,必须手动干预序列化过程或改用支持压缩的存储后端(如 Redis + 自定义 handler)才能实现真正有效的会话压缩。
session.serialize_handler 设置不能压缩数据
很多人误以为把 session.serialize_handler 改成 php_serialize 或 php_binary 就能压缩——其实这只是改变了序列化格式,和压缩无关。PHP 的序列化机制本身不包含压缩逻辑,serialize() 输出的是纯文本字节流,体积通常比原始数组还大。
-
php_serialize:兼容性好,支持复杂键名(含|、!),但无压缩 -
php/php_binary:有字符限制,且同样不压缩 - 无论哪种 handler,
$_SESSION写入前的数据仍是明文 PHP 结构,session_start()和session_write_close()之间不做任何压缩处理
可行方案:在 write 回调中手动压缩
真正起作用的方式是使用 session_set_save_handler() 自定义保存逻辑,在 write 阶段对序列化后的字符串做压缩;读取时在 read 阶段解压。这是唯一能在 PHP 8.1 原生文件存储下实现会话压缩的路径。
修复 Core bailout 状态损坏安全问题,以及 BZ2、DOM、PDO、Opcache/JIT 内存与执行错误,改进 Unicode 字素处理、URL 解析、TLS 流状态、信号分发及会话错误处理。
- 必须确保
zlib扩展已启用(gzencode/gzdecode可用) -
write($id, $session_data)中:先serialize($_SESSION)→ 再gzencode($data, 9)→ 存入文件或 DB -
read($id)中:读出压缩数据 →gzdecode()→unserialize() - 注意错误处理:
gzdecode()失败会返回false,需 fallback 到原始数据或清空会话
更推荐的替代方案:Redis + phpredis + 压缩中间层
比起自己写 handler,用 Redis 存储会话并配合轻量压缩逻辑更稳定、易维护,也天然规避文件锁问题。
立即学习“PHP免费学习笔记(深入)”;
- 配置
session.save_handler = redis和session.save_path = "tcp://127.0.0.1:6379?prefix=phpsess:" - 在
session_start()后、写入前,对大字段单独压缩:$_SESSION['big_data'] = gzencode(json_encode($arr), 6) - 读取时手动
json_decode(gzdecode($_SESSION['big_data'])) - 避免全量压缩整个
$_SESSION:Redis 本身不压缩,但值过大(>10KB)会影响网络和内存效率,按需压缩关键字段更可控
容易忽略的关键点
压缩不是万能优化。会话数据是否值得压缩,取决于实际大小与 CPU 开销的权衡。
- 小于 1KB 的会话数据,压缩后可能反而变大(gzip 有固定头部开销)
-
gzencode(..., 9)压缩率高但 CPU 消耗明显,线上建议用6级平衡 - PHP 8.1 的
opcache.enable_file_override=1不影响会话 handler,别指望它加速序列化 - 如果用了
session.use_strict_mode=1,自定义 handler 必须正确实现validateId(),否则压缩后 ID 校验可能失败


















