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 相关文章推荐
简单示例AJAX结合PHP代码实现登录效果代码
Jul 25 PHP
浅析php中常量,变量的作用域和生存周期
Aug 10 PHP
CI框架入门示例之数据库取数据完整实现方法
Nov 05 PHP
PHP中使用正则表达式提取中文实现笔记
Jan 20 PHP
php魔术函数__call()用法实例分析
Feb 13 PHP
PHP验证信用卡卡号是否正确函数
May 27 PHP
PHP7新增运算符用法实例分析
Sep 26 PHP
php结合redis高并发下发帖、发微博的实现方法
Dec 15 PHP
PHP如何读取由JavaScript设置的Cookie
Mar 22 PHP
如何修改Laravel中url()函数生成URL的根地址
Aug 11 PHP
PHP+mysql实现的三级联动菜单功能示例
Feb 15 PHP
Laravel框架源码解析之模型Model原理与用法解析
May 14 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
destoon数据库表说明汇总
2014/07/15 PHP
PHP中的命名空间相关概念浅析
2015/01/22 PHP
php实现根据词频生成tag云的方法
2015/04/17 PHP
PHP判断json格式是否正确的实现代码
2017/09/20 PHP
Ecshop 后台添加新功能栏目及管理权限设置教程
2017/11/21 PHP
jQuery 表单验证插件formValidation实现个性化错误提示
2009/06/23 Javascript
JavaScript 函数惰性载入的实现及其优点介绍
2013/08/12 Javascript
jQuery选择器全集详解
2014/11/24 Javascript
js关于命名空间的函数实例
2015/02/05 Javascript
jquery马赛克拼接翻转效果代码分享
2015/08/24 Javascript
Jquery跨域获得Json的简单实例
2016/05/18 Javascript
jQuery.ajax实现根据不同的Content-Type做出不同的响应
2016/11/03 Javascript
BootStrap便签页的简单应用
2017/01/06 Javascript
使用get方式提交表单在地址栏里面不显示提交信息
2017/02/21 Javascript
AngularJS+bootstrap实现动态选择商品功能示例
2017/05/17 Javascript
使用JavaScript根据图片获取条形码的方法
2017/07/04 Javascript
JS实现数组去重方法总结(六种方法)
2017/07/14 Javascript
对angularJs中ng-style动态改变样式的实例讲解
2018/09/30 Javascript
vue 解决在微信内置浏览器中调用支付宝支付的情况
2020/11/09 Javascript
[49:21]TNC vs VG 2019DOTA2国际邀请赛淘汰赛 胜者组赛BO3 第三场 8.20.mp4
2019/08/22 DOTA
python生成1行四列全2矩阵的方法
2018/08/04 Python
对python捕获ctrl+c手工中断程序的两种方法详解
2018/12/26 Python
pytorch使用tensorboardX进行loss可视化实例
2020/02/24 Python
python 中不同包 类 方法 之间的调用详解
2020/03/09 Python
tensorflow安装成功import tensorflow 出现问题
2020/04/16 Python
使用python求斐波那契数列中第n个数的值示例代码
2020/07/26 Python
canvas画图被放大且模糊的解决方法
2020/08/11 HTML / CSS
英国领先的酒类网上商城:TheDrinkShop
2017/03/16 全球购物
法国低价在线宠物商店:bitiba.fr
2020/07/03 全球购物
团委书记的竞聘演讲稿
2014/04/24 职场文书
吨的认识教学反思
2014/04/27 职场文书
旅游与酒店管理专业求职信
2014/07/21 职场文书
2014国庆节商场促销活动策划方案
2014/09/16 职场文书
SpringBoot工程下使用OpenFeign的坑及解决
2021/07/02 Java/Android
python 多态 协议 鸭子类型详解
2021/11/27 Python
CSS 鼠标选中文字后改变背景色的实现代码
2023/05/21 HTML / CSS