memcache客戶端實現集羣之一致性hash算法

一致性哈希的算法把取餘算法的等於號來選擇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/>";
    }

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章