必须将 session.save_handler 设为 redis,否则 PHP 仍使用 files 处理器,无视所有 Redis 配置;需同时启用 redis 扩展、正确设置 session.save_path 连接串,并重启 PHP-FPM 才生效。

必须把 session.save_handler 设为 redis,否则 PHP 根本不会尝试连接 Redis,所有配置都白搭。
为什么 session.save_handler = redis 必须显式设置
PHP 默认用 files 处理器,即使你装了 phpredis 扩展、写了 session.save_path,只要 session.save_handler 没改成 redis,PHP 就完全无视 Redis 配置,继续往 /tmp 写文件。
常见错误现象:
- phpinfo() 里能看到 redis 扩展已加载,但
session handler一栏还是files - Redis 里查不到任何以
PHPREDIS_SESSION:开头的 key - 日志里反复出现
Failed to write session data (files)(注意括号里是files,不是redis)
正确做法:
立即学习“PHP免费学习笔记(深入)”;
- 在
php.ini中取消注释或新增:session.save_handler = redis - 若用
php-fpm.d/www.conf覆盖配置,写成:php_value[session.save_handler] = redis - 代码中动态设(仅限单脚本):
ini_set('session.save_handler', 'redis'),且必须在session_start()前调用
session.save_path 的写法和常见坑
session.save_path 不是简单填个 IP+端口,它控制连接方式、认证、数据库编号,格式不对会静默失败。
审查 Remix v2 代码中的 v1 形态 meta 导出(v2 中为破坏性变更),cookie 安全漏洞(httpOnly、secure、密钥轮换),认证门位于错误层级,以及其他
典型写法及说明:
- 本地无密码:
tcp://127.0.0.1:6379(最常用) - 带密码:
tcp://127.0.0.1:6379?auth=your_password(?auth=是必须的,不能写成&password=或?password=) - 指定 DB 索引:
tcp://127.0.0.1:6379?database=2(默认是 0,多项目隔离时有用) - Redis Cluster 多节点:
tcp://192.168.1.10:7000,tcp://192.168.1.11:7000(需 phpredis ≥5.0,原生不支持)
容易踩的坑:
- 用了
unix:///var/run/redis/redis.sock却没确认 PHP 进程有读 socket 文件权限 - 写成
redis://127.0.0.1:6379(协议名应为tcp,不是redis) - 密码含特殊字符(如
/、@)未 URL 编码,导致解析失败
扩展、配置、重启三者缺一不可
光改配置不生效,是因为 PHP 进程还拿着旧的内存映射。必须确保三个环节全部到位:
- phpredis 扩展已安装并启用:在 phpinfo() 页面搜索
redis,确认 “Registered save handlers” 里包含redis -
session.save_handler和session.save_path已写入最终生效的配置文件(优先级:php-fpm.d/*.conf>php.ini>ini_set()) - 对应 PHP-FPM 进程已重启:
systemctl restart php-fpm-80(版本号要匹配,宝塔里点“重启”按钮也行)
验证是否生效:
- 访问一个只含
session_start(); var_dump($_SESSION);的页面,看是否报错 - 执行
redis-cli keys "PHPREDIS_SESSION:*",应能立刻看到新生成的 key - 检查 PHP 错误日志,不再出现
Unknown: Failed to write session data (redis)类报错
并发写入和过期时间的隐性限制
Redis 存 Session 不是万能银弹,有两个底层限制常被忽略:
-
session.gc_maxlifetime不能超过 2147483647 秒(约 68 年),否则 Redis 的SETEX命令会传负数 TTL,key 直接消失,表现为 session 写入后立即丢失 - PHP 原生 Redis handler 不做锁,高并发下多个请求同时写同一 session_id 可能覆盖数据;如需强一致性,得自己用
session_set_save_handler()实现加锁逻辑
实际部署时,别只盯着配置写对了,更要确认 Redis 连通性、权限、TTL 设置、以及 PHP 进程是否真加载了新配置——这三个环节任一出错,都会让 session 看似“配置成功”,实则完全不走 Redis。


















