WEB集群是我们在项目中常见的情况,但是通过负载均衡后,会造成session的不同步问题,最直观的现象就是用户登录以后,会出现已登录与未登 录的状态的不断切换。这是因为同一个IP访问同一个页面会被随机分配到不同的服务器上。下面天涯PHP博客[http://blog.phpha.com /]根据网上的资料整理下一些最常规的解决方案。
一、利用数据库同步session
在做多服务器session同步时我没有用这种方法,如果非要用这种方法的话,我想过二种方法:
1)用一个低端电脑建个数据库专门存放web服务器的session,或者,把这个专门的数据库建在文件服务器上,用户访问web服务器时,会去这个专门的数据库check一下session的情况,以达到session同步的目的。
2)这种方法是把存放session的表和其他数据库表放在一起,如果mysql也做了集群了话,每个mysql节点都要有这张表,并且这张session表的数据表要实时同步。
说明:用数据库来同步session,会加大数据库的负担,数据库本来就是容易产生瓶颈的地方,如果把session还放到数据库里面,无疑是雪上加霜。上面的二种方法,第一点方法较好,把放session的表独立开来,减轻了真正数据库的负担
二、利用cookie同步session
session是文件的形势存放在服务器端的,cookie是文件的形势存在客户端的,怎么实现同步呢?方法很简单,就是把用户访问页面产生的 session放到cookie里面,就是以cookie为中转站。你访问web服务器A,产生了session把它放到cookie里面了,你访问被分 配到web服务器B,这个时候,web服务器B先判断服务器有没有这个session,如果没有,在去看看客户端的cookie里面有没有这个 session,如果也没有,说明session真的不存,如果cookie里面有,就把cookie里面的sessoin同步到web服务器B,这样就 可以实现session的同步了。
说明:这种方法实现起来简单,方便,也不会加大数据库的负担,但是如果客户端把cookie禁掉了的话,那么session就无从同步了,这样会给网站带来损失;cookie的安全性不高,虽然它已经加了密,但是还是可以伪造的。
三、利用memcache同步session
memcache可以做分布式,如果没有这功能,他也不能用来做session同步。他可以把web服务器中的内存组合起来,成为一个”内存池”,不管是哪个服务器产生的sessoin都可以放到这个”内存池”中,其他的都可以使用。
优点:以这种方式来同步session,不会加大数据库的负担,并且安全性比用cookie大大的提高,把session放到内存里面,比从文件中读取要快很多。
缺点:memcache把内存分成很多种规格的存储块,有块就有大小,这种方式也就决定了,memcache不能完全利用内存,会产生内存碎片,如果存储块不足,还会产生内存溢出。
四、总结
上面三种方法都是可行的,
第一种方法,最影响系统速度的那种,不推荐使用;
第二种方法,效果不错,不过安全隐患一样的存在;
第三种方法,个人觉得第三种方法是最好的,推荐大家使用
五、web集群时利用memcache来同步session
1)模拟web集群
我启动了二个memcached进程,分别模拟二台服务器
- /usr/local/bin/memcached -d -m 1024 -c 3000 -u uenucom -p 12000 -P ./memcached.pid
- /usr/local/bin/memcached -d -m 1024 -c 3000 -u uenucom -p 13000 -P ./mem.pid
2)修改php的配置
- vi /usr/local/php/lib/php.ini
- session.save_handler = "memcache"
- memcache.hash_strategy = "consistent"
- session.save_path = "tcp://127.0.0.1:13000?weight=10,tcp://127.0.0.1:12000"
说明:第一行,session的储存方式是memcache;第二行,memcache的hash算法是consistent;第三行,session储存的地位;
3)重起apache
查看phpinfo
- session
- Session Supportenabled
- Registered save handlersfiles user sqlite memcache
- Registered serializer handlersphp php_binary
紧接着下面是
- session.save_pathtcp://127.0.0.1:13000,tcp://127.0.0.1:12000
4)做个简单测试
a)准备文件session.php
- php
- session_start();
- $_SESSION['username'] = "abcabc";
- echo session_id();
- ?>
b)显示session内容文件
- php
- $mem = new Memcache;
- $mem->addServer("127.0.0.1″,12000) or die ("Could not add server 12000″);
- $mem->addServer("127.0.0.1″,13000) or die ("Could not add server 13000″);
- $val = $mem->get('qp0mrob2ovcqle3u4lbr4obsa5');
- echo $val;
- ?>
c)结果是
- username|s:6:"abcabc";