安裝完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分佈保存