必须用 yii\redis\session 或 yii\web\dbsession 替换默认 yii\web\session,因其本地文件存储不支持多机共享,负载均衡下 session 无法跨服务器识别,导致登录态丢失;redis 需同时配置 redis 实例、session 组件及 keyprefix;dbsession 表结构需匹配 yii 版本。

必须用 yii\redis\Session 或 yii\web\DbSession 替换默认的 yii\web\Session,否则多机部署时登录态必然丢失。
为什么不能用默认文件存储?
默认 yii\web\Session 把 session 写在本地磁盘,单机开发没问题;但一上负载均衡,用户请求随机落到不同机器,session_start() 在另一台服务器上根本找不到对应文件——结果就是刚登录完刷新就 401,或者购物车清空。这不是 Bug,是设计使然。
- PHP 的
session.save_handler=files天然不共享 - Yii 不会自动跨机器同步文件 session
- 哪怕你只部署两台,只要没做 NFS 共享(不推荐),就等同于无 session
Redis 存储:三处配置缺一不可
只改 class 是最常见翻车点。你得同时配对 redis 连接、session 组件、key 前缀,漏一个就会报 Class 'Redis' not found 或 Failed to open redis connection。
- 先确保 PHP 已启用
php-redis扩展(不是predis),运行php -m | grep redis验证 - 在
config/web.php的components里定义 redis 实例,class必须是yii\redis\Connection,且hostname/port要真实可达 - 再配
session组件:class设为yii\redis\Session,redis字段值必须和上面 redis 实例名**完全一致**(比如都叫redis) - 加上
keyPrefix(如yii2_session:),避免和其他项目 key 冲突,也方便 Redis CLI 查看:KEYS yii2_session:*
数据库存储:建表语句必须匹配 Yii 版本
Yii 2.0.x 和 2.1+ 的 DbSession 表结构不兼容,直接套旧 SQL 会导致 SQLSTATE[HY000]: General error: 1364 Field 'data' doesn't have a default value 这类写入失败。
- Yii 2.0.x 用
yii\web\DbSession,建表字段是id VARCHAR(128) PRIMARY KEY、data LONGTEXT、expire INT - Yii 2.1+ 官方已转向 Redis,
DbSession仍可用但不带迁移脚本;得手动跑yii migrate/create create_session_table,或按文档手建 -
id字段必须设为主键 + 索引,否则高并发下SELECT ... FOR UPDATE会锁整张表,登录页响应卡顿甚至超时
验证配置是否真正生效
别只测“能登录”,那可能是前端 localStorage 或 cookie 伪状态在兜底。要确认 session 数据确实落到了新存储层:
- Redis 方案:连进 Redis CLI,执行
KEYS yii2_session:*,看到类似yii2_session:abc123...的 key;再GET一个,返回值是 PHP 序列化字符串(非空、长度明显 > 50 字节) - 数据库方案:查
SELECT data FROM session WHERE expire > UNIX_TIMESTAMP() LIMIT 1,data字段不能是空字符串或 NULL - 最狠一招:临时把
session组件的class改成yii\web\FakeSession,刷新页面立刻报错——说明配置被加载了,不是被忽略或覆盖
keyPrefix、表名、redis 实例名这些看着像“细节”的字段,上线前不核对,出问题时第一反应永远是查业务逻辑,没人会想到是配置里一个冒号没加对。











