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

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云数据库 Tair(兼容Redis),内存型 2GB
简介: 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处理器了

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
相关文章
|
5月前
|
缓存 NoSQL 网络安全
【Azure Redis 缓存】Azure Redis服务开启了SSL(6380端口), PHP如何访问缓存呢?
【Azure Redis 缓存】Azure Redis服务开启了SSL(6380端口), PHP如何访问缓存呢?
|
2月前
|
缓存 NoSQL PHP
Redis作为PHP缓存解决方案的优势、实现方式及注意事项。Redis凭借其高性能、丰富的数据结构、数据持久化和分布式支持等特点,在提升应用响应速度和处理能力方面表现突出
本文深入探讨了Redis作为PHP缓存解决方案的优势、实现方式及注意事项。Redis凭借其高性能、丰富的数据结构、数据持久化和分布式支持等特点,在提升应用响应速度和处理能力方面表现突出。文章还介绍了Redis在页面缓存、数据缓存和会话缓存等应用场景中的使用,并强调了缓存数据一致性、过期时间设置、容量控制和安全问题的重要性。
46 5
|
2月前
|
存储 NoSQL PHP
PHP与Redis结合使用,提升数据存储性能
随着互联网应用的发展,PHP与Redis的结合成为提升数据存储性能的重要手段。PHP作为流行的服务器端语言,常用于网站开发;Redis作为高性能内存数据库,以其快速读写能力,有效优化数据访问速度,减轻数据库压力。两者结合通过缓存机制显著提升应用响应速度,支持高并发场景下的稳定性和可扩展性。
|
2月前
|
存储 NoSQL 关系型数据库
PHP 使用 Redis
10月更文挑战第22天
45 6
|
3月前
|
PHP 数据库 开发者
PHP中的异常处理和自定义异常
【10月更文挑战第3天】在PHP编程中,异常处理是一个重要的话题。它允许开发者优雅地处理错误,提高代码的可读性和可维护性。本文将介绍如何在PHP中进行异常处理,包括基本的try-catch结构,以及如何创建和使用自定义异常类来处理特定的错误情况。通过实际示例,我们将看到如何使用异常处理机制来增强应用程序的健壮性和灵活性。
32 1
|
3月前
|
NoSQL Redis API
限流+共享session redis实现
【10月更文挑战第7天】
43 0
|
3月前
|
缓存 NoSQL 数据处理
原生php实现redis缓存配置和使用方法
通过上述步骤,你可以在PHP项目中配置并使用Redis作为高性能的缓存解决方案。合理利用Redis的各种数据结构和特性,可以有效提升应用的响应速度和数据处理效率。记得在实际应用中根据具体需求选择合适的缓存策略,如设置合理的过期时间,以避免内存过度消耗。
72 0
|
4月前
|
PHP 数据安全/隐私保护 UED
PHP中实现自定义错误处理与异常管理
【9月更文挑战第2天】在PHP开发过程中,错误处理和异常管理是保证应用健壮性的关键。本文将引导你了解如何在PHP中创建自定义错误处理器,并通过实际代码示例展示如何有效捕获和处理异常,确保你的应用程序能够优雅地处理运行时出现的问题。
|
4月前
|
搜索推荐 PHP UED
PHP中的异常处理与自定义错误页面
【8月更文挑战第33天】在PHP开发中,优雅地处理异常和错误是提升应用稳定性和用户体验的关键。本文将引导你理解PHP的异常处理机制,并教你如何创建自定义错误页面,以增强你的应用对错误的响应能力。从基本的错误类型到深入的异常捕获,再到实现个性化的用户提示,我们将一步步构建一个更加健壮的PHP应用。
43 4
|
4月前
|
NoSQL Linux Redis
Linux Redis 服务设置开机自启动
【9月更文挑战第2天】在 Linux 系统中,可使用两种方法设置 Redis 开机自启动:一是通过创建 `redis.service` 文件并利用 systemd 进行管理,包括定义服务参数和启动脚本;二是编辑 `/etc/rc.local` 文件,在其中添加启动命令。推荐使用 systemd 方法,因为它更符合现代 Linux 系统的设计理念。设置完成后,可通过 `sudo systemctl status redis.service` 检查服务状态。
624 3