LEN

【转】SESSION共享问题
<p>随着应用访问量的增加,单台服务器已经扛不住这样的访问压力,所以需要部署多台服务器,并需要做负载均...
扫描右侧二维码阅读全文
10
2017/01

【转】SESSION共享问题

<p>随着应用访问量的增加,单台服务器已经扛不住这样的访问压力,所以需要部署多台服务器,并需要做负载均衡。那么,默认的SESSION存储方式会造成用户不同时间访问不同服务器时SESSION丢失,进而导致用户登录状态丢失,这时需要使用SESSION共享来解决。<!--more--></p>
<h3 id="toc-04a">SESSION共享方案</h3>
<p>实现SESSION共享的方案大致有以下几种:</p>
<p>1) 基于NFS的SESSION共享 </p>
<p>NFS是Net FileSystem的简称,该方案相对简单,无需做过多的二次开发,仅需同步各个服务器的本地SESSION文件记录,缺点是NFS依托于复杂的安全 机制和文件系统,因此并发效率不高。</p>
<p>2) 基于数据库的SESSION共享 </p>
<p>这就是所说的SESSION入库,该方案实用性较强。它的缺点在于SESSION的并发读写能力取决于Mysql数据库的性能,同时需要实现SESSIONgc逻辑。</p>
<p>3) 基于COOKIE的SESSION共享 </p>
<p>这个方案相对比较陌生,但它在大型网站中使用比较普遍。原理是将全站用户的SESSION信息加密、序列化后以COOKIE的形式,统一种植在根域名下,利用浏览器访问该根域名下的所有二级域名站点时,会传递与之域名对应的所有COOKIE内容的特性,从而实现用户的COOKIESESSION在多服务间的共享访问。 缺点是需要一定的技术成本,创业型公司未必能安全、便捷地实施。</p>
<p>4) 基于内存缓存的SESSION共享 </p>
<p>采用内存缓存服务器(MemcacheRedis)作为SESSION的存储介质,因为内存缓存服务器一般都是共享型的,且其在并发处理能力上占据了绝对优势,所以该方案成为我的首选。</p>
<p>下面是采用Redis作为缓存服务器并在PHP语言环境下实现SESSION共享。</p>
<h3 id="toc-40d">基于缓存的SESSION共享</h3>
<p>基于RedisSESSION共享方案结构大致如下:</p>

alt

<h4 id="toc-f40">搭建Redis环境</h4>
<p>首先,需要搭建一个Redis服务器环境,方法见这里。</p>
<h4 id="toc-7da">更改SESSION存储介质</h4>
<p>这里介绍3种方法,分别为:</p>
<p>1) 直接修改php.ini配置</p>

session.<span class="hljs-attr">save_handler</span> = redis                          <span class="hljs-comment">#将session存储介质由File改为Redis</span>
session.<span class="hljs-attr">save_path</span> =<span class="hljs-string">"tcp://fanhaobai.com:6379?database=0&auth=fhb"</span>   <span class="hljs-comment">#更改session保存地址</span>
<blockquote> <p>需要说明的是,当Redis服务端设置了密码,需要在save_path配置中以GET方式传递auth值,当然也可以选择数据库。</p> </blockquote> <p>配置成功后,查看phpinfo如下图。</p> alt <p>2) 通过ini_set()设置配置</p> <p>在某些使用环境下,php.ini配置文件是不允许进行修改的,且这样的修改对全局有效,所以可以采用ini_set()函数来设置当前脚本有效的配置信息。</p> <p>只需在项目的入口文件位置增加以下内容:</p>
ini_set(<span class="hljs-string">"session.save_handler"</span>, <span class="hljs-string">"redis"</span>);        <span class="hljs-meta">#将session存储介质由File改为Redis</span>
ini_set(<span class="hljs-string">"session.save_path"</span>, <span class="hljs-string">"tcp://fanhaobai.com:6379?database=0&auth=fhb"</span>);     <span class="hljs-meta">#更改session保存地址</span>
<blockquote> <p>注意设置只是当前脚本有效,并未修改php.ini配置文件。</p> </blockquote> <p>3) 通过session_set_save_handler()自定义会话存储</p> <p>session_set_save_handler()函数支持对SESSION机制的open(打开)、close(关闭)、read(读) 、write(写) 、destroy(删除) 、gc(垃圾回收)这7种操作进行自定义更改。</p> <p>参考IDsd2536888所分享的SESSIONRedis分布式驱动来说明。</p>
  • 打开SESSION
<span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">open</span><span class="hljs-params">($savePath, $sessName)</span> </span>{
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">true</span>;
}
<ul> <li> 关闭SESSION </li> </ul>
<span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">close</span><span class="hljs-params">()</span> </span>{
    <span class="hljs-keyword">if</span> (<span class="hljs-keyword">$this</span>->options[<span class="hljs-string">"persistent"</span>] == <span class="hljs-string">"pconnect"</span>) {
        <span class="hljs-keyword">$this</span>->handler->close();
    }
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">true</span>;
}
<ul> <li> 读取SESSION </li> </ul>
<span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">read</span><span class="hljs-params">($sessID)</span> </span>{
    <span class="hljs-keyword">$this</span>->connect(<span class="hljs-number">0</span>);
    <span class="hljs-keyword">$this</span>-&gt;get_result = <span class="hljs-keyword">$this</span>->handler->get(<span class="hljs-keyword">$this</span>-&gt;options[<span class="hljs-string">"prefix"</span>].$sessID);
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">$this</span>->get_result;
}
<ul> <li> 写入SESSION </li> </ul>
<span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">write</span><span class="hljs-params">($sessID, $sessData)</span> </span>{
    <span class="hljs-keyword">if</span> (!$sessData || $sessData == <span class="hljs-keyword">$this</span>->get_result) {
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">true</span>;
    }
    <span class="hljs-keyword">$this</span>->connect(<span class="hljs-number">1</span>);
    $expire = <span class="hljs-keyword">$this</span>->options[<span class="hljs-string">"expire"</span>];
    $sessID = <span class="hljs-keyword">$this</span>->options[<span class="hljs-string">"prefix"</span>].$sessID;
    <span class="hljs-keyword">if</span>(is_int($expire) &amp;&amp; $expire > <span class="hljs-number">0</span>) {
        $result = <span class="hljs-keyword">$this</span>->handler->setex($sessID, $expire, $sessData);
    } <span class="hljs-keyword">else</span> {
        $result = <span class="hljs-keyword">$this</span>->handler->set($sessID, $sessData);
    }
    <span class="hljs-keyword">return</span> $result;
}
<ul> <li> 删除SESSION </li> </ul>
<span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">destroy</span><span class="hljs-params">($sessID)</span> </span>{
    <span class="hljs-keyword">$this</span>->connect(<span class="hljs-number">1</span>);
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">$this</span>-&gt;handler-&gt;delete(<span class="hljs-keyword">$this</span>->options[<span class="hljs-string">"prefix"</span>].$sessID);
}
<ul> <li> 垃圾回收 </li> </ul>
<span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">gc</span><span class="hljs-params">($sessMaxLifeTime)</span> </span>{
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">true</span>;
}
<h3 id="toc-25f">总结</h3> <p>其实第①和第②种,是PHP已经自动实现了基于RedisSESSION自定义存储过程,只需要修改配置即可,而第③种就需要我们自主实现自定义存储过程,本质上是一样的原理,建议使用第②种方法。</p> </div> 原文链接:https://fanhaobai.com/post/session-share.html
最后修改:2017 年 02 月 08 日 02 : 20 PM
如果觉得我的文章对你有用,请随意赞赏

发表评论