php 一致性hash,【转载】memcache分布式 [一致性hash算法] 的php实现
最近在看一些分布式方面的文章,所以就用php實現(xiàn)一致性hash來練練手,以前一般用的是最原始的hash取模做分布式,當(dāng)生產(chǎn)過程中添加或刪除一臺memcache都會造成數(shù)據(jù)的全部失效,一致性hash就是為了解決這個問題,把失效數(shù)據(jù)降到最低,相關(guān)資料可以google一下!
php實現(xiàn)效率有一定的缺失,如果要高效率,還是寫擴展比較好
經(jīng)測試,5個memcache,每個memcache生成100個虛擬節(jié)點,set加get1000次,與單個memcache直接set加get慢5倍,所以效率一般,有待優(yōu)化!
實現(xiàn)過程:
memcache的配置 ip+端口+虛擬節(jié)點序列號 做hash,使用的是crc32,形成一個閉環(huán)。
對要操作的key進行crc32
二分法在虛擬節(jié)點環(huán)中查找最近的一個虛擬節(jié)點
從虛擬節(jié)點中提取真實的memcache ip和端口,做單例連接
/**
*?一致性哈希memcache分布式,采用的是虛擬節(jié)點的方式解決分布均勻性問題,查找節(jié)點采用二分法快速查找
*?the?last?known?user?to?change?this?file?in?the?repository??
*?@author?nash.xiong?
*?@copyright?Copyright???2003-2012?phpd.cn
*?@license
*/
class?memcacheHashMap?{
private?$_node?=?array();
private?$_nodeData?=?array();
private?$_keyNode?=?0;
private?$_memcache?=?null;
//每個物理服務(wù)器生成虛擬節(jié)點個數(shù)?[注:節(jié)點數(shù)越多,cache分布的均勻性越好,同時set?get操作時,也更耗資源,10臺物理服務(wù)器,采用200較為合理]
private?$_virtualNodeNum?=?200;
private?function?__construct()?{
/*?放入配置文件?*/
$config?=?array(
'127.0.0.1:11211',
'127.0.0.1:11212',
'127.0.0.1:11213',
'127.0.0.1:11214',
'127.0.0.1:11215'
);
if?(!$config)?throw?new?Exception('Cache?config?NULL');
foreach?($config?as?$key?=>?$value)?{
for?($i?=?0;?$i?_virtualNodeNum;?$i++)?{
$this->_node[sprintf("%u",?crc32($value?.?'_'?.?$i))]?=?$value?.?'_'?.?$i;
}
}
ksort($this->_node);
}
private?function?__clone(){}
/**
*?單例,保證只有一個實例
*/
static?public?function?getInstance()?{
static?$memcacheObj?=?null;
if?(!is_object($memcacheObj))?{
$memcacheObj?=?new?self();
}
return?$memcacheObj;
}
/**
*?根據(jù)key做一致性hash后連接到一臺物理memcache服務(wù)器
*?@param?string?$key
*/
private?function?_connectMemcache($key)?{
$this->_nodeData?=?array_keys($this->_node);
$this->_keyNode?=?sprintf("%u",?crc32($key));
$nodeKey?=?$this->_findServerNode();
//如果超出環(huán),從頭再用二分法查找一個最近的,然后環(huán)的頭尾做判斷,取最接近的節(jié)點
if?($this->_keyNode?>?end($this->_nodeData))?{
$this->_keyNode?-=?end($this->_nodeData);
$nodeKey2?=?$this->_findServerNode();
if?(abs($nodeKey2?-?$this->_keyNode)?_keyNode))??$nodeKey?=?$nodeKey2;
}
var_dump($this->_node[$nodeKey]);
list($config,?$num)?=?explode('_',?$this->_node[$nodeKey]);
if?(!$config)?throw?new?Exception('Cache?config?Error');
if?(!isset($this->_memcache[$config]))?{
$this->_memcache[$config]?=?new?Memcache;
list($host,?$port)?=?explode(':',?$config);
$this->_memcache[$config]->connect($host,?$port);
}
return?$this->_memcache[$config];
}
/**
*?采用二分法從虛擬memcache節(jié)點中查找最近的節(jié)點
*?@param?unknown_type?$m
*?@param?unknown_type?$b
*/
private?function?_findServerNode($m?=?0,?$b?=?0)?{
$total?=?count($this->_nodeData);
if?($total?!=?0?&&?$b?==?0)?$b?=?$total?-?1;
if?($m?
$avg?=?intval(($m+$b)?/?2);
if?($this->_nodeData[$avg]?==?$this->_keyNode)?return?$this->_nodeData[$avg];
elseif?($this->_keyNode?_nodeData[$avg]?&&?($avg-1?>=?0))?return?$this->_findServerNode($m,?$avg-1);
else?return?$this->_findServerNode($avg+1,?$b);
}
if?(abs($this->_nodeData[$b]?-?$this->_keyNode)?_nodeData[$m]?-?$this->_keyNode))??return?$this->_nodeData[$b];
else?return?$this->_nodeData[$m];
}
public?function?set($key,?$value,?$expire?=?0)?{
return?$this->_connectMemcache($key)->set($key,?json_encode($value),?0,?$expire);
}
public?function?add($key,?$value,?$expire?=?0)?{
return?$this->_connectMemcache($key)->add($key,?json_encode($value),?0,?$expire);
}
public?function?get($key)?{
return?json_decode($this->_connectMemcache($key)->get($key),?true);
}
public?function?delete($key)?{
return?$this->_connectMemcache($key)->delete($key);
}
}
$runData['BEGIN_TIME']?=?microtime(true);
//測試一萬次set加get
for($i=0;$i<10000;$i++)?{
$key?=?md5(mt_rand());
$b?=?memcacheHashMap::getInstance()->set($key,?time(),?10);
}
var_dump(number_format(microtime(true)?-?$runData['BEGIN_TIME'],6));
$runData['BEGIN_TIME']?=?microtime(true);?$m=?new?Memcache;
$m->connect('127.0.0.1',?11211);
for($i=0;$i<10000;$i++)?{
$key?=?md5(mt_rand());
$b?=?$m->set($key,?time(),?0,?10);
}
var_dump(number_format(microtime(true)?-?$runData['BEGIN_TIME'],6));
//測試結(jié)果,采用一致性哈希分布效率比原生單臺速度相差5倍左右
總結(jié)
以上是生活随笔為你收集整理的php 一致性hash,【转载】memcache分布式 [一致性hash算法] 的php实现的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java中optionnull_用 op
- 下一篇: php5.6 开二级域名,PHP二级域名