/** * memcached 一致性hash,分佈式算法 * Class MemcacheCluster */ class MemcacheCluster { protected $nodes = array(); //服務器節點 protected $position = array(); //虛擬節點 protected $virtualNum = 32; //每一個節點有32個虛擬節點;具體數量也能夠 16 ,8等 public function hash($str) { //將字符串轉成32位符號整數 return sprintf("%u", crc32($str)); } //查找key 落到哪一個節點上 public function findNode($key) { $point = $this->hash($key); //先取圓環上最小的一個節點 //$key 哈希後比最大的節點都大就放到第一個節點 $node = current($this->position); //下面這個查找能夠後期優化爲二分查找法。 foreach ($this->position as $k => $v) { if ($point <= $k) { $node = $v; break; } } //復位數組指針 reset($this->position); return $node; } public function addNode($node) { if (isset($this->nodes[$node])) { return; } for ($i = 0; $i < $this->virtualNum; $i++) { $pos = $this->hash($node . '-' . $i); $this->position[$pos] = $node; //方便刪除對應的虛擬節點 $this->nodes[$node][] = $pos; } $this->sortPos(); } public function delNode($node) { if (!isset($this->nodes[$node])) { return; } //循環全部的虛節點,誰的值==指定的真實節點 ,就把他刪掉 foreach ($this->nodes[$node] as $k) { unset($this->position[$k]); } unset($this->nodes[$node]); } protected function sortPos() { //將虛擬節點排序 //把每一項按常規順序排列(Standard ASCII,不改變類型) ksort($this->position, SORT_REGULAR); } }