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


Posted in PHP onNovember 28, 2018

前言

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,输出结果如下所示:

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

再查看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的前两行,成功接管,舒服。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

PHP 相关文章推荐
php类
Nov 27 PHP
PHP编程中字符串处理的5个技巧小结
Nov 13 PHP
利用PHP扩展vld查看PHP opcode操作步骤
Mar 04 PHP
php代码书写习惯优化小结
Jun 20 PHP
解析coreseek for sphinx的使用
Jun 21 PHP
php冒泡排序、快速排序、快速查找、二维数组去重实例分享
Apr 24 PHP
JavaScript实现滚动栏效果的方法
Apr 27 PHP
Zend Framework框架之Zend_Mail实现发送Email邮件验证功能及解决标题乱码的方法
Mar 21 PHP
PHP实现验证码校验功能
Nov 16 PHP
Swoole实现异步投递task任务案例详解
Apr 02 PHP
Thinkphp5.0 框架视图view的比较标签用法分析
Oct 12 PHP
Laravel 解决419错误 -ajax请求错误的问题(CSRF验证)
Oct 25 PHP
php基于Redis消息队列实现的消息推送的方法
Nov 28 #PHP
php获取用户真实IP和防刷机制的实例代码
Nov 28 #PHP
PHP实现小程序批量通知推送
Nov 27 #PHP
Laravel学习笔记之Artisan命令生成自定义模板的方法
Nov 22 #PHP
关于PHP虚拟主机概念及如何选择稳定的PHP虚拟主机
Nov 20 #PHP
phpMyAdmin通过密码漏洞留后门文件
Nov 20 #PHP
ThinkPHP5 的简单搭建和使用详解
Nov 15 #PHP
You might like
扩展你的 PHP 之入门篇
2006/12/04 PHP
php实现的单一入口应用程序实例分析
2015/09/23 PHP
PHP+AJAX 投票器功能
2017/11/11 PHP
PHP实现图片防盗链破解操作示例【解决图片防盗链问题/反向代理】
2020/05/29 PHP
javascript Ext JS 状态默认存储时间
2009/02/15 Javascript
IE 条件注释详解总结(附实例代码)
2009/08/29 Javascript
jQuery客户端分页实例代码
2013/11/18 Javascript
关注jquery技巧提高jquery技能(前端开发必学)
2015/11/02 Javascript
微信小程序 封装http请求实例详解
2017/01/16 Javascript
详解用webpack的CommonsChunkPlugin提取公共代码的3种方式
2017/11/09 Javascript
微信小程序判断页面是否从其他页面返回的实例代码
2019/07/03 Javascript
原生js实现可兼容PC和移动端的拖动滑块功能详解【测试可用】
2019/08/15 Javascript
基于layui的下拉列表的数据回显方法
2019/09/24 Javascript
在vue中利用v-html按分号将文本换行的例子
2019/11/14 Javascript
[02:56]DOTA2上海特锦赛小组赛解说FreeAgain采访花絮
2016/02/27 DOTA
Python中的jquery PyQuery库使用小结
2014/05/13 Python
举例区分Python中的浅复制与深复制
2015/07/02 Python
Python下rrdtool模块的基本使用方法
2015/11/13 Python
Python3.6正式版新特性预览
2016/12/15 Python
Collatz 序列、逗号代码、字符图网格实例
2017/06/22 Python
Mac下Anaconda的安装和使用教程
2018/11/29 Python
ubuntu 18.04搭建python环境(pycharm+anaconda)
2019/06/14 Python
python正则表达式匹配不包含某几个字符的字符串方法
2019/07/23 Python
python多线程案例之多任务copy文件完整实例
2019/10/29 Python
python常见字符串处理函数与用法汇总
2019/10/30 Python
python手写均值滤波
2020/02/19 Python
python和go语言的区别是什么
2020/07/20 Python
scrapy在python爬虫中搭建出错的解决方法
2020/11/22 Python
HTML5添加禁止缩放功能
2017/11/03 HTML / CSS
党员创先争优心得体会
2014/09/11 职场文书
故意杀人案辩护词
2015/05/21 职场文书
《海上日出》教学反思
2016/02/23 职场文书
《哪吒之魔童降世》观后感:世上哪有随随便便的成功
2019/11/08 职场文书
CSS 文字装饰 text-decoration & text-emphasis 详解
2021/04/06 HTML / CSS
Python合并多张图片成PDF
2021/06/09 Python
Java面试题冲刺第十六天--消息队列
2021/08/07 面试题