当前位置:首页 > PHP教程 > php高级应用 > 列表

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

发布:smiling 来源: PHP粉丝网  添加日期:2021-11-02 09:29:24 浏览: 评论:0 

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,代码如下:

  1. <?php 
  2. class SessionManager{ 
  3.  
  4.  private $redis
  5.  private $sessionSavePath
  6.  private $sessionName
  7.  private $sessionExpireTime=30;//redis,session的过期时间为30s 
  8.  
  9.  public function __construct(){ 
  10.   $this->redis = new Redis();//创建phpredis实例 
  11.   $this->redis->connect('127.0.0.1',6379);//连接redis 
  12.   $this->redis->auth("107lab");//授权 
  13.   $retval = session_set_save_handler( 
  14.    array($this,"open"), 
  15.    array($this,"close"), 
  16.    array($this,"read"), 
  17.    array($this,"write"), 
  18.    array($this,"destroy"), 
  19.    array($this,"gc"
  20.   ); 
  21.   session_start(); 
  22.  } 
  23.  
  24.  public function open($path,$name){ 
  25.   return true; 
  26.  } 
  27.  
  28.  public function close(){ 
  29.   return true; 
  30.  } 
  31.  
  32.  public function read($id){ 
  33.   $value = $this->redis->get($id);//获取redis中的指定记录 
  34.   if($value){ 
  35.    return $value
  36.   }else
  37.    return ''
  38.   } 
  39.  } 
  40.  
  41.  public function write($id,$data){ 
  42.   if($this->redis->set($id,$data)){//以session ID为键,存储 
  43.    $this->redis->expire($id,$this->sessionExpireTime);//设置redis中数据的过期时间,即session的过期时间 
  44.    return true; 
  45.   } 
  46.  
  47.   return false; 
  48.  } 
  49.  
  50.  public function destroy($id){ 
  51.   if($this->redis->delete($id)){//删除redis中的指定记录 
  52.    return true; 
  53.   } 
  54.   return false; 
  55.  } 
  56.  
  57.  public function gc($maxlifetime){ 
  58.   return true; 
  59.  } 
  60.  
  61.  public function __destruct(){ 
  62.   session_write_close(); 
  63.  } 
  64.  

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文件,代码如下:
 
  1. <?php 
  2.  include('SessionManager.php'); 
  3.  new SessionManager(); 
  4.  $_SESSION['username'] = 'captain'

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

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

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

captain

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

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

测试完美~

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

Tags: Redis接管文件 存储Session

分享到: