本文目录导读:

在 PHP 中将 Session 存储到 Redis 是一种常见的优化方案,可以提高性能并支持分布式部署,以下是完整的实现方案:
基础配置方法
通过 PHP 配置文件(php.ini)
; 设置 session 处理器 session.save_handler = redis session.save_path = "tcp://127.0.0.1:6379" ; 可选配置 session.gc_maxlifetime = 3600 session.sid_length = 32
通过 PHP 代码配置(推荐)
<?php
// 在项目入口文件(如 index.php)中设置
// session_set_save_handler() 或 ini_set() 必须在 session_start() 之前调用
// 方法1:使用 ini_set
ini_set('session.save_handler', 'redis');
ini_set('session.save_path', 'tcp://127.0.0.1:6379');
// 方法2:使用 session_set_save_handler(自定义实现)
session_set_save_handler(
function($id) {
// 读取 session
$redis = getRedis();
return $redis->get('session:' . $id);
},
function($id, $data) {
// 写入 session
$redis = getRedis();
$redis->set('session:' . $id, $data, 3600); // 1小时过期
return true;
},
function($id) {
// 删除 session
$redis = getRedis();
$redis->del('session:' . $id);
return true;
},
function($id) {
// GC 垃圾回收
return true;
},
function($id) {
// session 启动
return true;
}
);
// 获取 Redis 连接(根据你的 Redis 客户端库实现)
function getRedis() {
static $redis = null;
if ($redis === null) {
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
$redis->auth('password'); // 如果有密码
}
return $redis;
}
// 最后开启 session
session_start();
?>
完整的高级配置示例
<?php
class RedisSessionHandler {
private $redis;
private $ttl;
private $prefix;
public function __construct($host = '127.0.0.1', $port = 6379, $password = null, $ttl = 3600, $prefix = 'PHPSESSID:') {
$this->ttl = $ttl;
$this->prefix = $prefix;
// 创建 Redis 连接
$this->redis = new Redis();
$this->redis->connect($host, $port);
if ($password) {
$this->redis->auth($password);
}
// 测试连接
if (!$this->redis->ping()) {
throw new Exception('Redis 连接失败');
}
}
// 打开会话
public function open($path, $name) {
return true;
}
// 关闭会话
public function close() {
return true;
}
// 读取会话
public function read($id) {
$key = $this->prefix . $id;
return $this->redis->get($key) ?: '';
}
// 写入会话
public function write($id, $data) {
$key = $this->prefix . $id;
return $this->redis->setex($key, $this->ttl, $data);
}
// 销毁会话
public function destroy($id) {
$key = $this->prefix . $id;
return $this->redis->del($key) > 0;
}
// 垃圾回收
public function gc($maxlifetime) {
return true; // Redis 自动处理过期
}
// 注册 session 处理函数
public function register() {
return session_set_save_handler(
[$this, 'open'],
[$this, 'close'],
[$this, 'read'],
[$this, 'write'],
[$this, 'destroy'],
[$this, 'gc']
);
}
}
// 使用示例
try {
// 创建 Redis session 处理器
$handler = new RedisSessionHandler(
'127.0.0.1',
6379,
'your_password', // Redis 密码(如果不需要则传 null)
3600, // 过期时间(秒)
'MYAPP:' // Redis key 前缀
);
// 注册处理器
$handler->register();
// 开始会话(必须在 register() 之后)
session_start();
// 设置 session 数据
$_SESSION['user_id'] = 123;
$_SESSION['username'] = 'admin';
// 读取 session 数据
echo $_SESSION['username'];
} catch (Exception $e) {
echo '错误: ' . $e->getMessage();
}
?>
使用 PhpRedis 扩展
<?php
// 确保已安装 redis 扩展
// pecl install redis
// 使用单台 Redis 服务器
ini_set('session.save_handler', 'redis');
ini_set('session.save_path', 'tcp://127.0.0.1:6379?database=2');
// 带密码认证
ini_set('session.save_path', 'tcp://127.0.0.1:6379?password=your_password&database=2');
// 带过期时间设置(在 session.gc_maxlifetime 中设置)
ini_set('session.gc_maxlifetime', 7200);
ini_set('session.cookie_lifetime', 7200);
session_start();
$_SESSION['name'] = 'value';
?>
使用 Predis(纯 PHP 客户端)
<?php
require 'vendor/autoload.php'; // 安装 Predis
// 创建 Predis 客户端
$redis = new Predis\Client([
'scheme' => 'tcp',
'host' => '127.0.0.1',
'port' => 6379,
'password' => 'your_password',
'database' => 2,
]);
// 自定义 session 处理器
class PredisSessionHandler implements SessionHandlerInterface {
private $redis;
private $ttl;
public function __construct($redis, $ttl = 3600) {
$this->redis = $redis;
$this->ttl = $ttl;
}
public function open($path, $name) {
return true;
}
public function close() {
return true;
}
public function read($id) {
return $this->redis->get("session:$id") ?: '';
}
public function write($id, $data) {
return $this->redis->setex("session:$id", $this->ttl, $data);
}
public function destroy($id) {
return $this->redis->del("session:$id") == 1;
}
public function gc($maxlifetime) {
return true;
}
}
// 注册处理器
$handler = new PredisSessionHandler($redis, 3600);
session_set_save_handler($handler, true);
session_start();
$_SESSION['data'] = 'some data';
集群配置(Redis Sentinel 或 Cluster)
<?php
// Redis Cluster 配置
$redisCluster = new RedisCluster(NULL, [
'127.0.0.1:7000',
'127.0.0.1:7001',
'127.0.0.1:7002',
]);
// 使用 Redis Cluster 作为 session 存储
$options = [
'scheme' => 'tcp',
'host' => '127.0.0.1',
'port' => 7000,
'timeout' => 2.0,
'persistent' => true,
];
$client = new Predis\Client($redisCluster, [
'prefix' => 'session:',
]);
class ClusterSessionHandler implements SessionHandlerInterface {
private $cluster;
public function __construct($cluster) {
$this->cluster = $cluster;
}
// ... 实现相同的方法,但使用 $this->cluster
}
session_set_save_handler(new ClusterSessionHandler($redisCluster), true);
session_start();
?>
性能优化建议
配置优化
<?php
// 高并发场景下的配置
ini_set('session.save_handler', 'redis');
ini_set('session.gc_maxlifetime', 86400); // 24小时
ini_set('session.cookie_lifetime', 86400);
ini_set('session.sid_length', 32); // 增加 SID 长度
ini_set('session.use_strict_mode', 1); // 严格模式
ini_set('session.use_only_cookies', 1); // 只使用 cookie
?>
Redis 配置优化
# redis.conf 中调整 maxmemory 512mb maxmemory-policy allkeys-lru # 或 volatile-lru save 900 1 appendonly yes
监控会话
<?php
// 监控 Redis 中的 session
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
// 查看所有 session keys
$sessionKeys = $redis->keys('PHPSESSID:*');
echo "当前会话数量: " . count($sessionKeys);
// 查看某个 session 的剩余时间
$remaining = $redis->ttl('PHPSESSID:abc123');
echo "剩余时间: {$remaining}秒";
// 手动清理过期 session
$redis->eval("return redis.call('SCAN', 0, 'MATCH', 'PHPSESSID:*', 'COUNT', 100)");
?>
注意事项
-
安全要求:
- 确保 Redis 有密码保护
- 使用 SSL/TLS 加密连接(生产环境)
- 不要把 Redis 暴露到公网
-
兼容性:
- 确保 PHP 版本 >= 5.6
- 需要安装 Redis 扩展或 Predis 库
-
故障处理:
- 配置 Redis 高可用(Sentinel/Cluster)
- 设置连接超时和重试机制
-
性能监控:
- 监控 Redis 内存和命中率
- 定期清理过期 session
这个方案可以有效解决传统文件存储 session 的性能问题,特别适合高并发和分布式部署场景。