tp6.0 session丢失根本原因是driver未显式配置或配置不完整:driver为空则静默跳过初始化,redis驱动下还需确保prefix非空、serialize一致、cookie_httponly显式设置且use_trans_sid关闭。

TP6.0 Session 丢失根本不是“随机故障”,而是 driver 没配或配错
ThinkPHP 6.0 不再默认启用 session 驱动,session.driver 为空时直接跳过初始化——你调用 session('user')、读写 $_SESSION 全部静默失败,不报错、不提示、不写日志。
必须显式配置 'driver' => 'redis'(或 'file'、'database'),且不能只写 'driver' => 'redis' 就完事。TP6 会检查整个 session.redis 配置块是否完整,漏一项就 fallback 到 file 驱动,你以为走 Redis,其实数据全在本地临时文件里,换机器、重启服务自然丢。
-
config/session.php中确认'driver'键存在且值非空 - 若用
.env,确保含SESSION_DRIVER=redis,且配置文件里通过Env::get('session.driver')正确读取 - 别依赖 TP5 的“没配就用 file”逻辑——TP6 不兼容这种隐式行为
Redis 驱动下 session_id 不变但数据总丢?查 prefix 和 serialize 是否一致
多个 TP 应用共用一个 Redis 实例(尤其只用 database => 0),若 session.prefix 为空,所有项目 session key 全挤在 think:session:abc123 这种格式下,A 登录后 B 刷新页面可能直接拿到 A 的 session 数据,或被顶掉。
更隐蔽的问题是序列化方式不一致:TP5 默认用 serialize(),TP6 默认用 json_encode()。混用会导致 Redis 里存的是 JSON 字符串,但 TP5 的反序列化器试图用 unserialize() 解析,结果 $_SESSION 始终为空。
- 强制设
'prefix' => 'tp6_admin:'(非空字符串,结尾带冒号更安全) - 若需兼容老数据或含资源句柄的 session,加
'serialize' => 'php' - 检查
session.redis.database是否明确指定(如1),别留null或注释掉
Session 写进 Redis 了,但换浏览器/重启服务就失效?看 cookie_httponly 和 use_trans_sid
PHP 8.1+ 默认禁用 session.use_strict_mode,但要求显式设置 cookie_httponly;而 session.use_trans_sid 若开启,会在 URL 后追加 PHPSESSID,配合重定向极易触发循环,导致 session 初始化失败或被覆盖。
典型现象:浏览器能看到 PHPSESSID Cookie,$_SESSION 可读可写,但 redis-cli keys 'think:session:*' 查不到任何 key——说明 session 根本没走 Redis,只是 file 驱动在撑场面。
- 在
config/session.php中显式设'cookie_httponly' => true - 确保
'use_trans_sid' => false(TP6 默认是 false,但某些迁移项目可能手动开了) - 若用 HTTPS,务必加
'cookie_secure' => true,否则 Chrome 等浏览器会拒收 Cookie
Redis 连得上,key 也写了,但 session 过期快或随机消失?盯住 maxmemory-policy 和 evicted_keys
Redis 内存不足时,若配置了 maxmemory-policy 为 allkeys-lru 或 volatile-lru,Session key 可能被误删——TP 写入时虽设了 expire,但 Redis 不保证一定等到 TTL 到期才清理。
另外,TP6 的 session.redis.expire 单位是秒,它控制的是 session 生命周期,不是 Redis key 的 TTL;实际写入时 TP 会自动调用 EXPIRE 命令,但若 Redis 自身内存策略激进,照样提前踢掉。
- 上线前用
redis-cli info | grep evicted_keys查是否有淘汰记录 - 生产环境建议设
maxmemory-policy noeviction,靠业务层控制容量 - 监控 Redis
used_memory和mem_fragmentation_ratio,避免内存碎片过高
真正卡住人的往往不是 Redis 连不上,而是 prefix 冲突、serialize 不一致、driver 静默 fallback 这几处——它们不报错,只让你反复怀疑是不是网络或代码逻辑问题。











