session共享

伴随网站业务规模和访问量的逐步发展,原本由单台服务器、单个域名的迷你网站架构已经无法满足发展需要。

此时我们可能会购买更多服务器,并且启用多个二级子域名以频道化的方式,根据业务功能将网站分布部署在独立的服务器上;或通过负载均衡技术(如:DNS轮询、Radware、F5、LVS等)让多个频道共享一组服务器。

 

我们把网站程序分布部署到多台服务器上,而且独立为几个二级域名,由于Session受实现原理的局限(PHP中Session默认以文件的形式保存在本地服务器的硬盘),使得我们的网站用户不得不经常在几个频道间来回输入用户名、密码登入,导致用户体验大打折扣;另外,原本程序可以直接从用户Session变量中读取的资料(如:昵称、积分、登入时间等),因为无法跨服务器同步更新Session变量,迫使开发人员必须实时读写数据库,从而增加了数据库的负担。

 

方案: 1.把session放到共享的设备上去,如nfs

NFS是Net FileSystem的简称,最早由Sun公司为解决Unix网络主机间的目录共享而研发。

这个方案实现最为简单,无需做过多的二次开发,仅需将共享目录服务器mount到各频道服务器的本地session目录即可,缺点是NFS依托于复杂的安全机制和文件系统,因此并发效率不高,尤其对于session这类高并发读写的小文件, 会由于共享目录服务器的io-wait过高,最终拖累前端WEB应用程序的执行效率


方案:2. 基于数据库的Session共享

首选当然是大名鼎鼎的Mysql数据库,并且建议使用内存表Heap,提高session操作的读写效率。这个方案的实用性比较强,相信大家普遍在使用,它的缺点在于session的并发读写能力取决于Mysql数据库的性能,同时需要自己实现session淘汰逻辑,以便定时从数据表中更新、删除session记录,当并发过高时容易出现表锁,虽然我们可以选择行级锁的表引擎,但不得不否认使用数据库存储Session还是有些杀鸡用牛刀的架势


方案:3. 基于Memcache的Session共享

Memcache由于是一款基于Libevent多路异步I/O技术的内存共享系统,简单的Key + Value数据存储模式使得代码逻辑小巧高效,因此在并发处理能力上占据了绝对优势,目前本人所经历的项目达到2000/秒 平均查询,并且服务器CPU消耗依然不到10%。

另外值得一提的是Memcache的内存hash表所特有的Expires数据过期淘汰机制,正好和Session的过期机制不谋而合,降低了过期Session数据删除的代码复杂度,对比“基于数据库的存储方案”,仅这块逻辑就给数据表产生巨大的查询压力 

1.首先安装memcache,以及memcache在php中的扩展

2.修改php.ini文件

session.save_handler = memcache
session.save_path = "tcp://127.0.0.1:11211"

使用多个 memcached server 时用逗号”,”隔开,并且和 Memcache::addServer() 文档中说明的一样,可以带额外的参数”persistent”、”weight”、”timeout”、”retry_interval” 等等,类似这样的:”tcp://host1:port1?persistent=1&weight=2,tcp://host2:port2″ 。

3.大功告成,重启apache和memcache看看phpinfo里的session配置是不是变成了memcache了。

4.自己的程序完全不用修改,系统已经自己去找memcache来做他的session宿主啦。
PS:如果不想整台服务器全局都是用memcache的话也可以用如下两种方法:

修改 .htaccess
php_value session.save_handler “memcache”
php_value session.save_path “tcp://127.0.0.1:11211″

修改程序
ini_set("session.save_handler","memcache");
ini_set("session.save_path","tcp://127.0.0.1:11211");

********************************************************************************************************************************

以上是基于php的memcache扩展的session共享,如果是基于memcached扩展的话稍有不同:

session.save_handler = memcached
session.save_path = "127.0.0.1:11211" (此处必须去掉tcp://,而memcache去不去掉tcp均可)

另外,如果服务器安装了php-fpm,在php.ini文件中我们可以看到session.save_path实际上是被注释掉的:

; for php-fpm, see /etc/php-fpm.d/*conf
;session.save_path = "/tmp"

通过第一行可知,要在php-fpm目录下的www.conf文件中添加:

php_value[session.save_handler] = memcached
php_value[session.save_path] = "127.0.0.1:11211"

phpinfo页面的Registered save handlers可以看到。如果设置不正确,会有"Cannot find save handler memcache"的错误提示。


memcache和memcached还有一点不同的是:

<?php
$memcache = memcache_connect('127.0.0.1', 11211);  //memcached中为addServer('127.0.0.1', 11211)
var_dump($memcache->get('3bbf03b9cedace4e0164a0c3d56712d1'));  //根据sessionid取值
?>
memcache输出:string(21) "aaa|s:10:"cww333cccc";"

memcached输出:bool(false) ,memcached中的key类似于:memc.sess.key.arsorbl4tj0p8pj6lg288rc2h1



posted @ 2014-06-28 22:43  moqiang02  阅读(190)  评论(0编辑  收藏  举报