1. 程式人生 > 程式設計 >如何用PHP實現分佈演算法之一致性雜湊演算法

如何用PHP實現分佈演算法之一致性雜湊演算法

傳統演算法缺陷

對於伺服器分佈,我們要考慮的東西有http://www.cppcns.com如下三點:資料平均分佈,查詢定位準確,降低宕機影響。

傳統演算法一般是將資料的鍵用演算法映射出數字,對其用伺服器數量取模,並根據結果選擇要儲存的伺服器。其能達到資料平均分佈和查詢定位準確的要求,並且優點是演算法簡單,存取時的計算量都比較小(在資料非常大時才會明顯)http://www.cppcns.com

但其有一個致命缺點,即一個伺服器宕機後的影響很大,我們可以推算一下一臺伺服器宕機後的影響:

  • 原有資料大部分丟失:伺服器數量減少一臺,取模數減1導致取模值錯亂,如果以前有N臺伺服器,那麼宕機後資料只有1/(n*(n-1))的資料能夠被準確查詢到。
  • 負載無法均衡導致集體宕機:如果沒有及時處理宕機的伺服器,那麼他的儲存任務將會被順序積累給它的下一個伺服器,那麼下一個伺服器也會很快被壓致宕機,如此一來,伺服器組很快會集體宕機。

演算法思想

一致性雜湊演算法是使用一定的雜湊演算法,將大量的資料平均對映到不同的儲存目標上,在保證其查詢準確性的同時,還要考慮其中一個儲存目標失效時,其他儲存目標對其責任儲存內容的負載均衡。

一致性雜湊演算法的實現思想不難理解,如圖:

如何用PHP實現分佈演算法之一致性雜湊演算法

1.用一定的雜湊演算法(雜湊函式等)將一組伺服器的多個(數目自己設定)節點隨機對映分散到0-232之間,由於其隨機分佈,保證了其資料平均分佈的特點;

2.用同一演算法計算要儲存資料的鍵,根據伺服器節點確定其儲存的伺服器結點,由於

程式設計客棧每次用同一演算法計算,所以得出的結果是相同的,使其查詢定位準確;

3.查詢資料時,再次用同一演算法計算鍵,並查詢伺服器的資料結點;

4.如果有一個伺服器宕機,消除其伺服器結點,並將資料放在下一個結點上,由於隨機節點位置的隨機性,所以資料被其他伺服器平均負載,也就降低了宕機影響。

需要注意的是,這個環形空間只是一個虛擬空間,只是表示了伺服器儲存的範圍和資料的落點,在進行儲存時,我們還要通過查詢到的落點,將資料放入對應的伺服器進行查改。

演算法實現

程式設計語言我們使用php來實現一致性雜湊演算法:

我們主要用到以下函式:

int crc32 ( string $str )
生成 st

程式設計客棧r 的 32 位迴圈冗餘校驗碼多項式。這通常用於檢查傳輸的資料是否完整。

string sprintf ( string $format [,mixed $args [,mixed $... ]] )
通過傳入的格式產生字串的特定格式形態。

實現如下:

class Consistance
{
    protected $num=24;          //設定每一個伺服器的節點數,數量越多,宕機時伺服器負載就會分佈得越平均,但也增大資料查詢消耗。
    protected $nodes=array();   //當前伺服器組的結點列表。

    //計算一個數據的雜湊值,用以確定位置
    public function make_hash($data)
    {
        return sprintf('%u',crc32($data));
    }

    //遍歷當前伺服器組的節點列表,確定需要儲存/查詢的伺服器
    public function set_loc($data)
    {
        $loc=self::make_hash($data);
        foreach ($this->nodes as $key => $val)
        {
            if($loc<=$key)
            {
      www.cppcns.com          return $val;
            }
        }
    }

    //新增一個伺服器,將其結點新增到伺服器組的節點列表內。
    public function add_host($host)
    {
        for($i=0;$i<$this->num;$i++)
        {
            $key=sprintf('%u',crc32($host.'_'.$i));
            $this->nodes[$key]=$host;   
        }
        ksort($this->nodes);        //對結點排序,這樣便於查詢。
    }

    //刪除一個伺服器,並將其對應節點從伺服器組的節點列表內移除。
    public function remove_host($host)
    {
        for($i=0;$i<$this->num;$i++)
        {
            $key=sprintf('%u',crc32($host.'_'.$i));
            unset($this->nodes[$key]);
        }
    }
}

我們用以下程式碼進行測試:

如何用PHP實現分佈演算法之一致性雜湊演算法

結果如下:

如何用PHP實現分佈演算法之一致性雜湊演算法

總結

演算法的實現到此,我們還可以對演算法進行優化,如在伺服器數量和每個伺服器節點數都很多的情況下,對查詢結點的過程進行優化,因為排序好的,可以用二分法進行查詢,加快查詢效率,這些,仁智各見吧。

另外,雖然nginx伺服器有一致性演算法的外掛,memcache和redis也都有相應的外掛,mysql的中介軟體有相應的整合,但是瞭解一致性雜湊演算法也很有意義。而且,我們也可以對其靈活使用,如對檔案等進行分散式管理等等。

以上就是如何用PHP實現分佈演算法之一致性雜湊演算法的詳細內容,更多關於用PHP實現分佈演算法之一致性雜湊演算法的資料請關注我們其它相關文章!