memcache客戶端實現叢集之一致性hash演算法
阿新 • • 發佈:2018-11-11
一致性雜湊的演算法把取餘演算法的等於號來選擇mem伺服器變成了大於號來選擇mem伺服器,這應該是才是關鍵,可以使一個鍵的mem伺服器落點變成是動態選擇(一個伺服器down掉然後選擇crc32(key)後大於這個伺服器的落點....)
新增虛擬節點,虛擬節點其實還是原來那幾臺伺服器,每個虛擬節點都對應一個真實的伺服器,起到分散節點的作用
原理如:關鍵點 hash環的理解和構建。
程式碼如下:libraries/MemCluster.php
<?php /** */ //一致性hash // 功能 新增節點; ;根據使用者資料key 獲取應該使用那臺node class MemCluster { 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(){ //正常比較單元,不改變型別 ksort($this->position, SORT_REGULAR); } }
測試程式碼 如下:contoller/Mem.php
public function test(){ $this->load->library('memcluster'); $memServerArr = array('192.168.0.1:6666', '192.168.0.2:8888', '192.168.0.3:9999'); foreach ($memServerArr as $mem){ $this->memcluster->addNode($mem); } $key = "goods:1688"; $memNode = $this->memcluster->findNode($key); echo $memNode,"<br/>"; $key = "goods:1689"; $memNode = $this->memcluster->findNode($key); echo $memNode,"<br/>"; $key = "goods:1670"; $memNode = $this->memcluster->findNode($key); echo $memNode,"<br/>"; $key = "goods:1671"; $memNode = $this->memcluster->findNode($key); echo $memNode,"<br/>"; $key = "goods:1672"; $memNode = $this->memcluster->findNode($key); echo $memNode,"<br/>"; $key = "goods:1673"; $memNode = $this->memcluster->findNode($key); echo $memNode,"<br/>"; $key = "order:1673"; $memNode = $this->memcluster->findNode($key); echo $memNode,"<br/>"; $key = "order:1674"; $memNode = $this->memcluster->findNode($key); echo $memNode,"<br/>"; $key = "order:1675"; $memNode = $this->memcluster->findNode($key); echo $memNode,"<br/>"; $key = "post:1675"; $memNode = $this->memcluster->findNode($key); echo $memNode,"<br/>"; }