文档章节

PHP中使用Redis接管文件存储Session详解

开元中国2015
 开元中国2015
发布于 2018/12/04 09:48
字数 1108
阅读 65
收藏 1

前言

php默认使用文件存储session,如果并发量大,效率会非常低。而redis对高并发的支持非常好,可以利用redis替换文件来存储session。

最近就遇到了这个问题,之前找了网上的一套直播系统给客户用,刚开始是没问题的,在后面人数上来之后网站开始变得卡顿,卡的一批。之后查看php慢日志发现session_start()的身影,好吧,原来是万恶的文件存储session,跟我之前进的坑一模一样……之前做的教务查询系统直接用的session没有用cookie,结果在高并发的情况下php原地爆炸。

[0x00007fff67ee6740] session_start()
[0x00007fff67ee7b70] +++ dump failed

解决方案

  • 将session全面更换为cookie
  • 使用mysql或redis接管session

坑中坑

因为这套直播系统一没有用框架,二没有设计规范,各种session操作散落在不同的文件里,用第一个解决方案完全属于费力不讨好。再者直播系统的聊天互动等功能已经涉及大量的mysql操作,再用mysql接管session变相的增加了数据库的压力,最终确定了使用redis接管session。

具体实现

php有内置的操作session的save_handler,使用session_set_save_handler,接管所有的session管理工作。在使用该函数前,先把php.ini配置文件的session.save_handler选项设置为user,否则session_set_save_handle不会生效。另外除了安装redis之外,php扩展也需要增加redis。

(以下代码来源于网络,也不知道原创是哪位大佬)

编写一个session管理类sessionManager.php,代码如下:

<?php
class SessionManager{
private $redis;
private $sessionSavePath;
private $sessionName;
private $sessionExpireTime=30;//redis,session的过期时间为30s
public function __construct(){
$this->redis = new Redis();//创建phpredis实例
$this->redis->connect('127.0.0.1',6379);//连接redis
$this->redis->auth("107lab");//授权
$retval = session_set_save_handler(
array($this,"open"),
array($this,"close"),
array($this,"read"),
array($this,"write"),
array($this,"destroy"),
array($this,"gc")
);
session_start();
}
public function open($path,$name){
return true;
}
public function close(){
return true;
}
public function read($id){
$value = $this->redis->get($id);//获取redis中的指定记录
if($value){
return $value;
}else{
return '';
}
}
public function write($id,$data){
if($this->redis->set($id,$data)){//以session ID为键,存储
$this->redis->expire($id,$this->sessionExpireTime);//设置redis中数据的过期时间,即session的过期时间
return true;
}
return false;
}
public function destroy($id){
if($this->redis->delete($id)){//删除redis中的指定记录
return true;
}
return false;
}
public function gc($maxlifetime){
return true;
}
public function __destruct(){
session_write_close();
}
}

SessionManager构造函数主要用来连接Redis服务器,使用session_set_save_handler函数设置session回调函数,并调用session_start函数开启session功能。因为本例中open、close和gc回调函数的作用不是很大,所以直接返回true。

在write回调函数中,以session ID 作为key,把session的数据作为value存储到redis服务器,设置session的过期时间为30秒。在read回调函中,以session ID 作为key从redis服务器中读取数据,并返回此数据。而在destroy回调函数重,则以session ID 作为key 从redis服务器中删除对应的session数据。

使用时,只需包含SessionManager类,然后实例化一个SessionManager对象。

下面建立个session_set.php文件,代码如下:

<?php
include('SessionManager.php');
new SessionManager();
$_SESSION['username'] = 'captain';

然后再创建一个session_get.php文件,代码如下:

<?php
include('SessionManager.php');
new SessionManager();
echo $_SESSION['username'];

测试时,首先访问session_set.php,然后再访问session_get.php,输出结果如下所示:

再查看redis数据库,如下所示:

127.0.0.1:6379> keys *
1) "oe94eic337slnjv1bvlreoa574"
127.0.0.1:6379> get oe94eic337slnjv1bvlreoa574
"username|s:7:\"captain\";"

测试完美~

然后将原系统中的session_start()替换成session_set.php的前两行,成功接管,舒服。

您可能感兴趣的文章:

文章同步发布: https://www.geek-share.com/detail/2754800685.html

© 著作权归作者所有

开元中国2015
粉丝 45
博文 71
码字总数 99608
作品 0
大兴
私信 提问
分布式Session集中存储方案

在文章分布式web架构中Session管理的方法中讲了分布式Session管理的4种办法,其中第4种的Session集中存储实际运用比较广泛,下面来讲解这种的实现方案。 目前常用的Session集中管理方案有两种...

刘诗书
2017/11/23
0
0
PHP7优化提高性能的几个Tips

PHP7已经发布了, 作为PHP10年来最大的版本升级, 最大的性能升级, PHP7在多放的测试中都表现出很明显的性能提升, 然而, 为了让它能发挥出最大的性能, 我还是有几件事想提醒下. 1. Opcache 记得...

English0523
2015/12/29
0
0
J2Cache 2.6.0 发布,支持分布式 session 存储管理

J2Cache 2.6.0 版本发布啦,该版本最最值得关注的就是支持分布式的 session 存储管理,支持不同的 Servlet 容器。 此外,该版本包含了如下小改动: 配置中对值包含空格的处理 CacheObject 允...

红薯
2018/09/13
2K
29
一篇文章让你深透理解cookie和session,附带分布式WEB系统redis共享session方案

cookie和session有什么区别?这是一个很基础的知识点,大家可能都知道一个大概:cookie是存在客户端的,session是存储在服务端,cookie和session用来验证识别用户的登录状态,常见适用场景:...

狗子2018
2017/08/16
0
0
redis慢查询日志,php安装redis扩展,redis存储session,redis主从配置

笔记内容:redis慢查询日志,php安装redis扩展,redis存储session,redis主从配置笔记日期:2018-1-03 21.18 redis慢查询日志 21.19 php安装redis扩展 21.20 redis存储session 21.21 redis主...

ZeroOne01
2018/01/03
0
0

没有更多内容

加载失败,请刷新页面

加载更多

发布npm包

1、在NPM网站上注册,并验证(verify)自己的邮箱,一定要验证,不然在发布时会提示你 https://www.npmjs.com 2、在命令行里登录npm, 按提示依次输入用户名 密码 注册邮箱 PS {你本地库的文...

羊皮卷
17分钟前
2
0
数组

数组:可以理解为是一个巨大的“盒子”,里面可以按顺序存放多个类型相同的数据,比如可以定义 int 型的数组 scores 存储 4 名学生的成绩 数组中的元素都可以通过下标来访问,下标从 0 开始。...

Lao鹰
17分钟前
3
0
Spark internal

SparkStream 如何使用checkpoint ? 都 9102 年了,就不要用 RDD 和 DStream API 了吧…… DataFrame/Dataset 和 Structured Streaming 是在RDD 和 DStream 上层. Spark SQL and DataFram......

MtrS
今天
9
0
Kafka实战(五) - 核心API及适用场景全面解析

1 四个核心API ● Producer API 允许一个应用程序发布一串流式的数据到一个或者多个Kafka topic。 ● Consumer API 允许一个应用程序订阅一个或多个topic ,并且对发布给他们的流式数据进行处...

JavaEdge
今天
13
0
实现线程的第三种方式——Callable & Future

Callable Runnable 封装一个异步运行的任务, 可以把它想象成为一个没有参数和返回值的异步方 法。Callable 与 Runnable 类似, 但是有返回值。Callable 接口是一个参数化的类型, 只有一 个...

ytuan996
今天
15
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部