安装完memcached之后
参考安装memcached客户端
在php.ini中
将session.save_handler 修改为memcache,并修改save_path指向memcached的地址和端口即可
session.save_handler = memcache
session.save_path = tcp://127.0.0.1:10001
Memcache的PECL这个扩展非常强大
可以支持failover以及分布存储
使用方法很讲但.
只需要在session.save_path的参数列表中
使用逗号分隔各个memcached服务器
则保存的session会经过hash之后保存到各个mc服务器中
而hash的算法.memcache支持两种,crc32以及fnv
memcache.hash_function= {crc32,fnv}
文档中很少有提到fnv算法的,据说其散列要比crc32更好
但是我通过以下小小的程序实验之后,发现仍旧是crc32的散列算法分布的更加平均.
<?php ini_set("memcache.hash_function","crc32"); $memcache = new Memcache; $memcache1 = new Memcache; $memcache2 = new Memcache; $memcache->addServer('localhost', 11211); $memcache->addServer('localhost', 11212); $memcache->flush(); $memcache1->connect('localhost',11211); $memcache2->connect('localhost',11212); $fp1 = fopen("mem1.txt","w"); $fp2 = fopen("mem2.txt","w"); for($i=0;$i<1000;$i++){ $memcache->set($i,$i,0,1000); fwrite($fp1,$memcache1->get($i)." "); fwrite($fp2,$memcache2->get($i)." "); } fclose($fp1); fclose($fp2); ?>
接着我就session的保存进行了测试
我开了3个memcached进程进行测试
<?php ini_set("memcache.hash_function","fnv"); ini_set("error_reporting","E_CORE_ERROR"); $memcache1 = new Memcache; $memcache1->connect('localhost',11211); $memcache1->flush(); $memcache2 = new Memcache; $memcache2->connect('localhost',11212); $memcache2->flush(); $memcache3 = new Memcache; $memcache3->connect('localhost',11213); $memcache3->flush(); $fp1 = fopen("mem1.txt","w"); $fp2 = fopen("mem2.txt","w"); $fp3 = fopen("mem3.txt","w"); for($i=0;$i<1000;$i++){ session_start(); $ssid=session_id(); echo $ssid; session_register("id"); $_SESSION["id"]=$ssid; session_write_close(); fwrite($fp1,$memcache1->get($ssid)." "); fwrite($fp2,$memcache2->get($ssid)." "); fwrite($fp3,$memcache3->get($ssid)." "); //session_destroy(); } fclose($fp1); fclose($fp2); fclose($fp3); ?>
比较奇怪的是.memcached2一般都会不被选中
而1,3的内容是一致的.可能是为了failover
而当我把1,3关闭一台后.2中将会出现内容,说明memcached2是正常工作的
而不论我的散列算法使用crc32还是fnv
这种现象都存在
最后我发现.这个测试程序存在问题
因为在session_write_close之后.整个程序的session都是唯一的了.
也就是虽然循环了这么多次.里面包含了session_destroy调用.但是返回的session id都是同样的
这就导致了两个文件中的内容一致而另一个文件中没有内容
基于此点
我只能分次调用脚本,脚本修改如下
<?php ini_set("memcache.hash_strategy","consistent"); ini_set("memcache.hash_function","crc32"); ini_set("error_reporting","E_CORE_ERROR"); ini_set("memcache.allow_failover","0"); $memcache1 = new Memcache; $memcache1->connect('localhost',10001); $memcache1->flush(); $memcache2 = new Memcache; $memcache2->connect('localhost',10002); $memcache2->flush(); $memcache3 = new Memcache; $memcache3->connect('localhost',10003); $memcache3->flush(); $fp1 = fopen("mem1.txt","a+"); $fp2 = fopen("mem2.txt","a+"); $fp3 = fopen("mem3.txt","a+"); session_start(); $ssid=session_id(); echo $ssid."\n"; session_register("id"); $_SESSION["id"]=$ssid; //session_destroy(); session_write_close(); fwrite($fp1,$memcache1->get($ssid)." "); fwrite($fp2,$memcache2->get($ssid)." "); fwrite($fp3,$memcache3->get($ssid)." "); session_destroy(); fclose($fp1); fclose($fp2); fclose($fp3); ?>
然后再shell中重复运行多次.返回的ID不同了
再打开mem*.txt文件查看
发现3个文件中,每个session会保存在其中两个文件.然后分布不同
这证明了使用memcache来保存session.一个是做到了failover.第二会按照session id来做hash分布保存