PHP设置Redis储存Session,自定义session驱动

简介: PHP也可以配置将session保存在redis或者memcache中,在几种用来存储会话数据的方式。显然是Redis在效率上要更快些,而与memcached相比,因为有持久化,也更安全一些。 所以也是常用的负载均衡环境处理session的策略。 但因为是将信息储存在内存中,可能会出现内存不足、利用率不高等问题。 优点:效率高 缺点:信息储存在内存中,会产生大小不一的内存块,内存无法完全利用,并且可能出现内存不足。


我们在之前的文章已经讲到了session是将数据储存在本地文件中,并且将session_id返回给客户端(浏览器会储存在cookies里)。 那么当我们在负载均衡集群环境的时候,负载调度部分负责把客户端的请求按照不同的策略分配给后端服务节点。所以会出现我们在A机器设置了session,后面请求在B机器判断session依旧为空的情况。


常用的负载均衡环境处理session的策略


PHP也可以配置将session保存在redis或者memcache中,在几种用来存储会话数据的方式。显然是Redis在效率上要更快些,而与memcached相比,因为有持久化,也更安全一些。 所以也是常用的负载均衡环境处理session的策略。 但因为是将信息储存在内存中,可能会出现内存不足、利用率不高等问题。 优点:效率高 缺点:信息储存在内存中,会产生大小不一的内存块,内存无法完全利用,并且可能出现内存不足。


设置session处理


php中除了可以通过简单修改配置项来设定使用其他的session处理方式,同时也提供了对应的接口以便于我们自定义session的处理逻辑。 接下来我们来通过自定义redis处理session的逻辑来了解接口。


session_set_save_handler函数


session_set_save_handler()该函数定义用户session逻辑,如写入、取出、关闭等。 该函数的传参如下:


该函数有两种用法


在PHP5.4以前的用法


bool session_set_save_hanler(callback open,callback close,callback read,callback write,callback destory,callback gc)


可见该函数的几个参数接收都是以callback回调函数的形式的。


参数


描述


open


session打开时的回调函数。接收两个参数,第一个参数是保持session的路径,第二个参数是session的名字


close


当session操作完成时调用此函数。不接收参数。


read


以session_id作为参数。通过以session_id作为参数从数据存储方中取得数据,并返回此数据。如果数据为空,可以返回一个空字符串。此函数在调用session_start 前被触发


write


当数据存储时调用。接收两个参数,一个是session_id,另外一个是session的数据


destory


当调用session_destroy 函数时触发destroy函数。只有一个参数 session_id


gc


当php执行session垃圾回收机制时触发


调用方式:


<?php 
// 需要先引入自定义的SiamSession类(该类的实现逻辑于下面PHP5.4以后的实现相同),然后再设置到save_handler中去
// 也可以直接在参数处传递闭包
$siamSession = new SiamSession();
session_set_save_handler(
  [$siamSession,"open"],
  [$siamSession,"close"],
  [$siamSession,"read"],
  [$siamSession,"write"],
  [$siamSession,"destroy"],
  [$siamSession,"gc"]
);
// 开启
session_start();


※※※


在PHP5.4以后的用法 也是推荐的用法


session_set_save_handler ( object sessionhandler[,boolsessionhandler[,boolregister_shutdown = TRUE ] ) : bool


参数


描述


sessionhandler


实现了 (SessionHandlerInterface, SessionIdInterface)或 SessionUpdateTimestampHandlerInterface 接口的对象, 例如 SessionHandler


register_shutdown


将函数 session_write_close() 注册为 register_shutdown_function() 函数。在PHP函数停止执行时可以触发。


session_write_close()函数:结束当前会话并存储会话数据。


调用方式:


<?php 
// 需要先引入自定义的Session处理程序,然后再设置到save_handler中去
// 也可以直接在参数处传递闭包
$siamSession = new SiamSession();
session_set_save_handler($siamSession, true);
// 开启
session_start();


我们看到第一个参数的描述,传入的参数应该是一个实现了 SessionHandlerInterface 接口的对象 同时还可以附属实现 SessionIdInterfaceSessionUpdateTimestampHandlerInterface 接口 那么我们先来看看这几个接口需要实现什么方法


从SessionHandler理解几个接口实现


在描述中可以看到举例传入的参数可以为SessionHandler,也就是如果我们想要自定义Session处理程序,可以参考该类需要实现的方法。


  • 这个类是设计用于公开当前内部PHP Session处理程序,如果想要自己实现PHP Session处理程序,请实现 SessionHandlerInterface接口


  • 从SessionHandler继承的类,可以通过调用父类方法来重写覆盖具体操作,例如将数据加密储存。并且将新类通过session_set_save_handler()设置为PHP Session处理程序


<?php
// SessionHandler 实现了SessionHandlerInterface和SessionIdInterface两个接口
// 其中 SessionIdInterface 提供了 create_sid 接口,可以自定义session_id的生成规则
// 其他的方法则由 SessionHandlerInterface 提供,主要是session的回调处理,如打开、关闭、gc、写入、读取
SessionHandler implements SessionHandlerInterface , SessionIdInterface {
    /**
     * close方法,当session关闭的时候触发
     */
    public close ( void ) : bool
    /**
     * create_sid方法,返回一个新创建的session_id
     */
    public create_sid ( void ) : string
    /**
     * destroy方法,当调用session_destroy的时候触发
     */
    public destroy ( string $session_id ) : bool
    /**
     * gc方法,当php程序gc清理的时候触发,主要用于清除已经过期的session
     */
    public gc ( int $maxlifetime ) : int
    /**
     * open方法,当session打开的时候触发
     */
    public open ( string $save_path , string $session_name ) : bool
    /**
     * read方法,读取session的处理逻辑,可以在这里解密储存数据
     * 在session_start后会触发
     */
    public read ( string $session_id ) : string
    /**
     * write方法,将session数据写入到储存中,可以在这里加密数据
     */
    public write ( string $session_id , string $session_data ) : bool
}


还有另一个接口是SessionUpdateTimestampHandlerInterface 我们看看它又提供了什么方法的接口


SessionUpdateTimestampHandlerInterface {
    /**
     * 更新时间戳,即更新session过期时间的
     */
    abstract public updateTimestamp ( string $key , string $val ) : bool
    /**
     * 验证session_id 是否还在线
     */ 
    abstract public validateId ( string $key ) : bool
}

SessionHandlerInterface 接口是PHP >= 5.4.0 提供的 SessionIdInterface 接口是PHP >= 5.5.1 提供的 SessionUpdateTimestampHandlerInterface 接口是PHP >= 7.0 提供的



接下来我们通过代码来实践一下,通过实现SessionHandlerInterface接口,来写一个redis的PHP Session处理程序


<?php
class SiamSession  implements \SessionHandlerInterface
{
    private $redis;
    private $expTime = 30; // 默认超时时间 根据业务场景设置
    function __construct(){
        // 连接redis
        $this->redis = new Redis();
        $this->redis->connect('127.0.0.1',6379);
        // 设置session处理回调 并且将session_write_close注册为register_shutdown_function函数
        session_set_save_handler($this, true);
        // 开启
        session_start();
    }
    function open($path, $name)
    {
        return true;
    }
    function close(){
        return true;
    }
    function read($session_id)
    {
        $value = $this->redis->get("siam_".$session_id);
        if ($value){
            return $value;
        }
        return '';
    }
    function write($session_id, $data)
    {
        if( $this->redis->set("siam_".$session_id, $data) ){
            $this->redis->expire("siam_".$session_id, $this->expTime);
            return true;
        }
        return false;
    }
    function destroy($session_id)
    {
        if ( $this->redis->delete("siam_".$session_id) )
        {
            return true;
        }
        return false;
    }
    function gc($maxlifetime)
    {
        return true; // 因为redis设置了过期时间,不需要再gc回收
    }
    function __destruct()
    {
        session_write_close();
    }
}
new SiamSession();


接着我们在另一个文件中写下测试代码


<?php
require_once "SiamSession.php";
$_SESSION['name'] = "siam";
echo $_SESSION['name'];

可以看到浏览器正常出现了siam 那么我们进入phpredisadmin查看一下数据 可以看到类似图片的情况


error_icon.png


其他的储存可以参考上面的处理,对数据进行处理,就可以实现自己的session处理器了

目录
相关文章
|
缓存 NoSQL PHP
Redis作为PHP缓存解决方案的优势、实现方式及注意事项。Redis凭借其高性能、丰富的数据结构、数据持久化和分布式支持等特点,在提升应用响应速度和处理能力方面表现突出
本文深入探讨了Redis作为PHP缓存解决方案的优势、实现方式及注意事项。Redis凭借其高性能、丰富的数据结构、数据持久化和分布式支持等特点,在提升应用响应速度和处理能力方面表现突出。文章还介绍了Redis在页面缓存、数据缓存和会话缓存等应用场景中的使用,并强调了缓存数据一致性、过期时间设置、容量控制和安全问题的重要性。
261 5
|
存储 NoSQL 关系型数据库
PHP 使用 Redis
10月更文挑战第22天
202 6
|
存储 NoSQL PHP
PHP与Redis结合使用,提升数据存储性能
随着互联网应用的发展,PHP与Redis的结合成为提升数据存储性能的重要手段。PHP作为流行的服务器端语言,常用于网站开发;Redis作为高性能内存数据库,以其快速读写能力,有效优化数据访问速度,减轻数据库压力。两者结合通过缓存机制显著提升应用响应速度,支持高并发场景下的稳定性和可扩展性。
|
NoSQL PHP Redis
Mac PHP安装Redis扩展
php安装redis的扩展 采用pecl命令进行安装; pecl命令,在使用brew 安装php时,已经为我们安装上了,这里我们直接使用即可。 我们先进入php的bin目录看下命令是否存在,对应路径如下: cd /opt/homebrew/Cellar/php@7.3/7.3.32 这里的7.3为我通过brew install [php@7.3]安装的php具体版本号,大家可以通过ls命令查看文件夹下是否存在pecl命令
1645 0
|
NoSQL PHP Apache
windows下PHP安装Redis扩展不成功的可能原因
windows下PHP安装Redis扩展不成功的可能原因
613 0
windows下PHP安装Redis扩展不成功的可能原因
|
NoSQL Linux PHP
php7安装redis6扩展
php7安装redis6扩展
255 0
|
NoSQL PHP Redis