PHP设置Redis储存Session

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云数据库 Tair(兼容Redis),内存型 2GB
简介: PHP设置Redis储存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 \[, bool $register\_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
}
``````php
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查看一下数据 可以看到类似图片的情况

image.png

其他的储存可以参考上面的处理,对数据进行处理,就可以实现自己的session处理器了
Siam博客原文链接:http://yancoo.cn/index/article/show/id/60.html
相关实践学习
基于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
目录
相关文章
|
1月前
|
存储 NoSQL PHP
PHP与Redis结合使用,提升数据存储性能
随着互联网应用的发展,PHP与Redis的结合成为提升数据存储性能的重要手段。PHP作为流行的服务器端语言,常用于网站开发;Redis作为高性能内存数据库,以其快速读写能力,有效优化数据访问速度,减轻数据库压力。两者结合通过缓存机制显著提升应用响应速度,支持高并发场景下的稳定性和可扩展性。
|
1月前
|
存储 NoSQL 关系型数据库
PHP 使用 Redis
10月更文挑战第22天
34 6
|
3月前
|
存储 缓存 数据处理
php学习笔记-php会话控制,cookie,session的使用,cookie自动登录和session 图书上传信息添加和修改例子-day07
本文介绍了PHP会话控制及Web常用的预定义变量,包括`$_REQUEST`、`$_SERVER`、`$_COOKIE`和`$_SESSION`的用法和示例。涵盖了cookie的创建、使用、删除以及session的工作原理和使用,并通过图书上传的例子演示了session在实际应用中的使用。
php学习笔记-php会话控制,cookie,session的使用,cookie自动登录和session 图书上传信息添加和修改例子-day07
|
2月前
|
缓存 NoSQL 数据处理
原生php实现redis缓存配置和使用方法
通过上述步骤,你可以在PHP项目中配置并使用Redis作为高性能的缓存解决方案。合理利用Redis的各种数据结构和特性,可以有效提升应用的响应速度和数据处理效率。记得在实际应用中根据具体需求选择合适的缓存策略,如设置合理的过期时间,以避免内存过度消耗。
56 0
|
3月前
|
NoSQL Linux Redis
Linux Redis 服务设置开机自启动
【9月更文挑战第2天】在 Linux 系统中,可使用两种方法设置 Redis 开机自启动:一是通过创建 `redis.service` 文件并利用 systemd 进行管理,包括定义服务参数和启动脚本;二是编辑 `/etc/rc.local` 文件,在其中添加启动命令。推荐使用 systemd 方法,因为它更符合现代 Linux 系统的设计理念。设置完成后,可通过 `sudo systemctl status redis.service` 检查服务状态。
474 3
|
3月前
|
消息中间件 NoSQL Go
PHP转Go系列 | ThinkPHP与Gin框架之Redis延时消息队列技术实践
【9月更文挑战第7天】在从 PHP 的 ThinkPHP 框架迁移到 Go 的 Gin 框架时,涉及 Redis 延时消息队列的技术实践主要包括:理解延时消息队列概念,其能在特定时间处理消息,适用于定时任务等场景;在 ThinkPHP 中使用 Redis 实现延时队列;在 Gin 中结合 Go 的 Redis 客户端库实现类似功能;Go 具有更高性能和简洁性,适合处理大量消息。迁移过程中需考虑业务需求及系统稳定性。
|
NoSQL Java 应用服务中间件
|
NoSQL Java 应用服务中间件
使用redis进行基于shiro的session集群共享
之前写过一篇nginx多tomcat负载均衡,主要记录了使用nginx对多个tomcat 进行负载均衡,其实进行负载均衡之前还有一个问题没有解决,那就是集群间的session共享,不然用户在登录网站之后session保存在tomcat A,但是下次访问的时候nginx分发到了tomcat B,这个时...
1147 0
|
NoSQL Java 应用服务中间件
使用redis进行基于shiro的session集群共享
之前写过一篇nginx多tomcat负载均衡,主要记录了使用nginx对多个tomcat 进行负载均衡,其实进行负载均衡之前还有一个问题没有解决,那就是集群间的session共享,不然用户在登录网站之后session保存在tomcat A,但是下次访问的时候nginx分发到了tomcat B,这个时...
1375 0
|
2月前
|
消息中间件 缓存 NoSQL
Redis 是一个高性能的键值对存储系统,常用于缓存、消息队列和会话管理等场景。
【10月更文挑战第4天】Redis 是一个高性能的键值对存储系统,常用于缓存、消息队列和会话管理等场景。随着数据增长,有时需要将 Redis 数据导出以进行分析、备份或迁移。本文详细介绍几种导出方法:1)使用 Redis 命令与重定向;2)利用 Redis 的 RDB 和 AOF 持久化功能;3)借助第三方工具如 `redis-dump`。每种方法均附有示例代码,帮助你轻松完成数据导出任务。无论数据量大小,总有一款适合你。
78 6