ThinkPHP 6.x 切 Redis Session 需两步:配置 session.driver 为 redis 并关闭 PHP 原生 session(session.use_trans_sid 和 auto_start 设为 Off);同时必须区分 session 与 cache 的 Redis key 前缀,避免误删,并以 session.max_lifetime 控制过期时间。

ThinkPHP 的 session 驱动怎么切到 Redis?
直接改配置就行,但必须同时关掉 PHP 原生 session 机制,否则 Redis 写了、$_SESSION 还是走文件。ThinkPHP 6.x 默认用的是 FileSession,要换成 RedisSession,核心是两步:session.driver 改为 redis,且确保 session.use_trans_sid 和 session.auto_start 在 PHP 配置里是 Off(TP 不会帮你关)。
常见错误现象:页面没报错,但登录后刷新就掉登录态;或者 Redis 里能看到 key,但 $_SESSION 读不到——八成是 PHP 自己还在用 session_start() 拉文件驱动。
-
config/session.php中设置'driver' => 'redis' - 确认
'redis' => ['host' => '127.0.0.1', 'port' => 6379, 'password' => '', 'select' => 0]可连通(建议加timeout和database字段,避免默认库冲突) - 删掉或注释掉
ini_set('session.save_handler', 'files')类干扰代码(尤其在中间件或公共函数里)
为什么 Redis Session 的 key 前缀不能共用缓存前缀?
因为 session 和 cache 是两个独立驱动,各自维护 key 命名空间。如果都用同一个 prefix(比如 tp6:),Redis 里 session key 就会和缓存 key 混在一起,FLUSHDB 或 KEYS tp6:* 会误伤 session 数据,线上可能批量登出。
更麻烦的是 ThinkPHP 的 RedisCache 和 RedisSession 虽然底层都用 Predis\Client 或 phpredis,但初始化时互不感知——你给 cache 配了 prefix => 'cache:',session 完全不知道,它只认自己的 session.redis.prefix 配置项。
立即学习“PHP免费学习笔记(深入)”;
- session 专用前缀配在
config/session.php的'redis' => ['prefix' => 'sess:'] - cache 前缀配在
config/cache.php的'stores.redis.prefix' => 'cache:' - 别图省事写成一样的字符串,哪怕只是加个冒号后缀也要区分开,比如
sess:login:vscache:home:
session.gc_maxlifetime 在 Redis 下还生效吗?
不生效。Redis 本身没有“自动过期并触发回调”的机制,ThinkPHP 的 RedisSession 完全依赖 Redis 的 EXPIRE 命令设 TTL,而这个 TTL 是写入 session 时由 session.max_lifetime(不是 gc_maxlifetime)决定的。
PHP 的 gc_maxlifetime 只对文件驱动有意义,它控制 PHP 的垃圾回收进程多久扫一次过期文件。Redis 驱动下,这个值被忽略,真正起作用的是 session.max_lifetime,它会被直接当作 SETEX 或 EXPIRE 的秒数传给 Redis。
- 务必检查
config/session.php中的'max_lifetime' => 3600(单位秒),别依赖 php.ini 里的session.gc_maxlifetime - 如果用的是
phpredis扩展,TTL 设置是原子的;用Predis时注意版本,老版本( - 线上发现 session 突然大面积失效?先查 Redis 的
TTL返回值,再核对max_lifetime是否被运行时覆盖
Redis 连接断了 session 会静默失败吗?
会,而且默认不报错。ThinkPHP 的 RedisSession 在连接失败时,多数操作(如 read()、write())会返回空或 false,但框架层不会中断请求,$_SESSION 就变成空数组,用户感觉就是“登着登着就没了”。
这不是 bug,是设计取舍:不能因为 Redis 挂了就让整个站 500。但问题在于,它连日志都不打,默认静默吞掉异常。生产环境必须自己兜底。
- 在
session.php中开启'redis' => ['failover' => true](仅限 Predis)或手动加异常捕获中间件 - 更稳妥的做法:重写
think\session\driver\Redis,在read()和write()方法开头加if (!$this->handler->isConnected()) { throw new \RuntimeException('Redis session connection lost'); } - 监控层面,定期
redis-cli -h x.x.x.x ping+ 检查KEYS sess:* | wc -l是否异常归零
Redis session 看似配置简单,但 session 生命周期、key 隔离、故障表现这三块,稍不注意就会在凌晨三点把你叫醒。尤其是前缀混用和连接静默失败,线上最难排查的就是这两类“看起来没问题”的配置。











