必须用Redis集群替代文件型Session存储,PHP需安装≥5.0版phpredis扩展,Redis部署三主三从集群并设密码,PHP通过php.ini或代码配置rediscluster handler,Yii2需自定义RedisClusterSessionHandler类实现Session共享。

在PHP多节点Web集群中实现Session共享,必须将默认的文件型Session存储替换为集中式Redis后端,否则用户登录后跳转即登出、购物车数据丢失、后台权限校验失败等问题会持续发生。
确认PHP Redis扩展已就绪
执行php -m | grep redis,输出必须为redis——若显示predis或无任何输出,说明未安装phpredis扩展或装错了库。
运行php --ri redis检查版本:必须≥5.0;低于该版本无法使用RedisCluster类,后续所有集群配置都会触发Class 'RedisCluster' not found致命错误。
若版本不达标,需卸载旧版后用PECL重装:pecl uninstall redis && pecl install redis,再确认extension=redis.so已写入php.ini并重启php-fpm。
立即学习“PHP免费学习笔记(深入)”;
部署Redis集群服务(三主三从最小可用拓扑)
在Redis服务器上执行以下命令快速启动6节点集群:
./tests/make-cluster.sh start -y
该脚本自动创建7000–7005共6个端口的实例,完成节点握手与槽位分配。默认不启用密码,生产环境务必在每个节点的redis.conf中添加requirepass your_strong_password并重启服务。
【集群必须至少3个主节点,否则RedisCluster构造时会因无法满足哈希槽覆盖而抛出异常】
配置PHP使用Redis集群存取Session
方法一:直接修改php.ini(适用于所有PHP应用统一管控)
在php.ini中定位到session.save_handler段,替换为:
session.save_handler = rediscluster
session.save_path = "redis-node1.example.com:7000,redis-node2.example.com:7001,redis-node3.example.com:7002"
session.rediscluster.auth = "your_strong_password"
注意:save_path中每个节点格式必须是host:port,不可带tcp://前缀,也不能用逗号分隔后加空格。
方法二:在PHP代码中动态设置(适用于单应用隔离场景)
在入口文件(如index.php)顶部加入:
ini_set('session.save_handler', 'rediscluster');
ini_set('session.save_path', 'redis-node1.example.com:7000,redis-node2.example.com:7001,redis-node3.example.com:7002');
ini_set('session.rediscluster.auth', 'your_strong_password');
然后调用session_start()即可生效——此方式无需重启PHP服务,但每次请求都需重复执行,性能略低。
Yii2.0.48项目专用:替换Session组件为集群适配版
第一步:在config/web.php的'components'数组内注册Redis连接组件:
复制以下配置,严格替换hostname、port、password为实际值:
'redis' => [
'class' => 'yii\redis\Connection',
'hostname' => 'redis-node1.example.com',
'port' => 7000,
'password' => 'your_strong_password',
'database' => 0,
'clusters' => [
'redis-node1.example.com:7000',
'redis-node2.example.com:7001',
'redis-node3.example.com:7002',
],
],
【'clusters'必须是字符串数组,每个元素格式为"host:port",不能含tcp://,也不能用逗号拼成单个字符串】
第二步:创建自定义Session处理器
在项目根目录新建components/RedisClusterSessionHandler.php,内容如下:
<?php
namespace app\components;
use SessionHandlerInterface;
class RedisClusterSessionHandler implements SessionHandlerInterface {
private $cluster;
private $prefix = 'yii2_session:';
public function __construct(array $nodes) {
$this->cluster = new \RedisCluster(NULL, $nodes);
}
public function read($id) {
return $this->cluster->get($this->prefix . '{' . $id . '}') ?: '';
}
public function write($id, $data) {
$key = $this->prefix . '{' . $id . '}';
$lifetime = (int)ini_get('session.gc_maxlifetime');
return $this->cluster->setex($key, $lifetime, $data);
}
public function destroy($id) { $this->cluster->del($this->prefix . '{' . $id . '}'); }
public function gc($maxlifetime) { return true; }
public function close() { return true; }
public function open($savePath, $sessionName) { return true; }
}
第三步:在config/web.php中覆盖默认Session组件:
'session' => [
'class' => 'yii\web\Session',
'handler' => [
'class' => 'app\components\RedisClusterSessionHandler',
'nodes' => [
'redis-node1.example.com:7000',
'redis-node2.example.com:7001',
'redis-node3.example.com:7002',
],
],
],



















