PHP 使用memcache/memcached实现session共享
参考自:
【Memcached】使用Memcache实现共享Session【原创】_一直加班的程序猿-CSDN博客_memcached做session共享
将session的值存储到memcached中去,配置以及方法和注意事项_yanlintao1的专栏-CSDN博客
问题:
这种session共享是为了解决集群中session丢失问题的其中一种方法
原因:
用户登录态是保存在Session中,默认是保存在文件中的,且没有做共享Session,导致在某一台登录成功之后,写入到Session文件中,然后刷新页面就有可能请求到另一台服务器上,而另一台服务器中的Session文件是没有该登录态的,就会导致服务器认为用户没有登录需要重新登录
解决方法:
一般业界通用的 有两种:
- 使用 IP_HASH 做会话保持(Session保持):每个请求按访问ip的hash结果分配,这样每个访客固定访问一个后端服务器,达到了Session保持的方法。
- 使用 Redis/Memcache等Nosql来做会话共享(Session共享):把Session放在一个统一的地方,集群中的所有节点都在这个地方进行Session的存取
Session保持(会话保持)是我们见到最多的名词之一,通过会话保持,负载均衡进行请求分发的时候保证每个客户端固定的访问到后端的同一台应用服务器。会话保持方案在所有的负载均衡都有对应的实现。而且这是在负载均衡这一层就可以解决Session问题。
会话保持看似解决了Session同步的问题,但是却带来的一些其它方面的问题:
负载不均衡了:由于使用了Session保持,很显然就无法保证负载绝对的均衡。
没有彻底解决问题:如果后端有服务器宕机,那么这台服务器的Session丢失,被分配到这台服务请求的用户还是需要重新登录。
所以一般呢,更加推荐使用 Redis/Memcache等Nosql来做会话共享(Session共享)
前提:
1. 安装服务器端Memcached
2. web服务器端安装php的memcache/memcached扩展
实现方法:
实现Session共享,其实就是把Session的存储,从默认的文件存储改成使用Memcache来存储即可,一共三种方法,推荐第一种
第一种方法:直接在php.ini配置文件修改(推荐)
第一步:开启memcache扩展,并运行memcache。
第二步:将php.ini配置文件中的session.save_handler=memcache
第三步:将php.ini配置文件中的session.save_path="tcp://127.0.0.1:11211"
第四步:重启php服务
注意:如果客户端使用的是php的memcached扩展而不是memcache,那么 session.save_path的值要把 "tcp://" 去掉,变为如下
1 session.save_handler=memcached 2 session.save_path="127.0.0.1:11211"
之后,查看phpinfo()中配置是否生效,另外一台web服务器上也做相同的操作,如此便可实现session的共享
注意:如果修改后发现phpinfo页面还是指向默认的文件缓存地址/tmp,说明还有其他的Session配置,在Linux中php-fpm的配置文件:/etc/php-fpm.conf或者/etc/php-fpm.d/*.conf中,而且它们的优先级比php.ini高,会覆盖php.ini中的配置,所以也需要在这里面修改:
1 # memcache扩展,如果有多个memcached服务端的话,用逗号,隔开 2 php_value[session.save_handler] = memcache 3 php_value[session.save_path] = "tcp://127.0.0.1:11211" 4 5 # memcached扩展,如果有多个memcached服务端的话,用逗号,隔开 6 php_value[session.save_handler] = memcached 7 php_value[session.save_path] = "127.0.0.1:11211"
第二种方法:设置.htaccess
在某个目录下,修改.htaccess:
# memcache扩展,如果有多个memcached服务端的话,用逗号,隔开 php_value session.save_handler "memcache" php_value session.save_path "tcp://127.0.0.1:11211" # memcached扩展,如果有多个memcached服务端的话,用逗号,隔开 php_value session.save_handler "memcached" php_value session.save_path "127.0.0.1:11211"
这个方法一般不推荐
第三种方法:通过php函数ini_set函数来自动动态修改配置,且只作用于本页面即临时配置,不会修改到原php.ini。
ini_set("session.save_handler","memcache");
ini_set("session.save_path","tcp://127.0.0.1:11211");
<?php # memcache扩展,如果有多个memcached服务端的话,用逗号,隔开 ini_set("session.save_handler", "memcache"); ini_set("session.save_path", "tcp://127.0.0.1:11211"); # memcached扩展,如果有多个memcached服务端的话,用逗号,隔开 ini_set("session.save_handler", "memcached"); ini_set("session.save_path", "127.0.0.1:11211");
注意:
(1)在session数据存储到memcached时,键值对中的键是以session_id为键存储
(2)如果存入多个session,则它是以session_id为key名的数组存入的。
(3)如果session中存入对象时,对象被序列化后存入memcached。
代码:
使用memcached扩展
1 // Memcached 2 // 1. 先测试下session存取 3 session_start(); 4 $_SESSION['name'] = '李斯'; 5 $_SESSION['name2'] = '韩非'; 6 print($_SESSION['name'] . '<br/>'); // 李斯 session可以正常设置读取 7 8 // 2. 查看一下是否是以session_id为键存储的 9 $mem = new Memcached(); 10 $mem->addServer('127.0.0.1', 11211); 11 $res = $mem->get('memc.sess.key.' . session_id()); // string(18) "name|s:6:"李斯";name2|s:6:"韩非";" 12 print($res . '<br/>'); 13 14 // 3. 再查看下memcached可以正常使用否 15 $mem->set('age', 20, 60); 16 $res1 = $mem->get('age'); // 20 //说明memcached还可以正常使用 17 print($res1);
使用memcache扩展
1 // Memcache 2 // 1. 先测试下session存取 3 session_start(); 4 $_SESSION['name'] = '李斯'; 5 $_SESSION['name2'] = '韩非'; 6 print($_SESSION['name'] . '<br/>'); // 李斯 session可以正常设置读取 7 8 // 2. 查看一下是否是以session_id为键存储的 9 $mem = new Memcache(); 10 $mem->addServer('127.0.0.1', 11211); 11 $res = $mem->get(session_id()); // string(18) "name|s:6:"李斯";name2|s:6:"韩非";" 12 print($res . '<br/>'); 13 14 // 3. 再查看下memcached可以正常使用否 15 $mem->set('age', 20, MEMCACHE_COMPRESSED, 60); 16 $res1 = $mem->get('age'); // 20 //说明memcached还可以正常使用 17 print($res1);
注意:
上面两段代码的第11行,memcache存储的key名是session_id(),而memcached存储的key名是 'memc.sess.key' . session_id()