zoukankan      html  css  js  c++  java
  • PHP中如何使用Redis接管文件存储Session详解

    https://www.jb51.net/article/151580.htm

    前言

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

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

     

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

    解决方案

    • 将session全面更换为cookie

    • 使用mysql或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的前两行,成功接管

  • 相关阅读:
    PHP 使用 GET 传递数组变量
    Java实现 蓝桥杯 算法训练 数据交换
    Java实现 蓝桥杯 算法训练 数据交换
    Java实现 蓝桥杯 算法训练 数据交换
    Java实现 蓝桥杯 算法训练 景点游览
    Java实现 蓝桥杯 算法训练 景点游览
    Java实现 蓝桥杯 算法训练 景点游览
    Java实现 蓝桥杯 算法训练 二进制数数
    Java实现 蓝桥杯 算法训练 二进制数数
    Java实现 蓝桥杯 算法训练 二进制数数
  • 原文地址:https://www.cnblogs.com/lxwphp/p/10217942.html
Copyright © 2011-2022 走看看