PHP session存储到Redis

wen PHP项目 1

本文目录导读:

PHP session存储到Redis

  1. 基础配置方法
  2. 完整的高级配置示例
  3. 使用 PhpRedis 扩展
  4. 使用 Predis(纯 PHP 客户端)
  5. 集群配置(Redis Sentinel 或 Cluster)
  6. 性能优化建议
  7. 注意事项

在 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)");
?>

注意事项

  1. 安全要求

    • 确保 Redis 有密码保护
    • 使用 SSL/TLS 加密连接(生产环境)
    • 不要把 Redis 暴露到公网
  2. 兼容性

    • 确保 PHP 版本 >= 5.6
    • 需要安装 Redis 扩展或 Predis 库
  3. 故障处理

    • 配置 Redis 高可用(Sentinel/Cluster)
    • 设置连接超时和重试机制
  4. 性能监控

    • 监控 Redis 内存和命中率
    • 定期清理过期 session

这个方案可以有效解决传统文件存储 session 的性能问题,特别适合高并发和分布式部署场景。

抱歉,评论功能暂时关闭!