「分佈式哈希」和「一致性哈希」的概念與算法實現

分佈式哈希和一致性哈希是分佈式存儲和p2p網絡中說的比較多的兩個概念了。介紹的論文不少,這裏作一個入門性質的介紹。php

  分佈式哈希(DHT)
  兩個key point:每一個節點只維護一部分路由;每一個節點只存儲一部分數據。從而實現整個網絡中的尋址和存儲。
DHT只是一個概念,提出了這樣一種網絡模型。而且說明它是對分佈式存儲頗有好處的。但具體怎麼實現,並非DHT的範疇。html

  一致性哈希:
  DHT的一種實現。本質仍是一個哈希算法。回想平時咱們作負載均衡,按querystring簽名對後端節點取模是最簡單也是最經常使用的算法,但節點的增刪後所形成的問題顯而易見,原有的請求幾乎都落不到同一臺機器上。優化一點的是carp算法(用機器ip和querystring一塊兒作hash,選取hash值最小的一臺),只讓1/n的數據受到影響。
一致性哈希,彷佛最先提出是在分佈式cache裏面的,讓節點震盪的時候,影響最小,以提升分佈式cache的命中率。不過如今更多的應用在分佈式存儲和p2p系統裏面。算法

  一致性哈希也只是提出四個概念和原則,並無說起具體實現:後端

  一、balance:哈希結果儘量的平均分散到各個節點上,使得每一個節點都能獲得充分利用。網絡

  二、Monotonicity:上面也說了,若是是用簽名取模算法,節點變動會使得整個網絡的映射關係更改。若是是carp,會使得1/n的映射關係更改。一致性哈希的目標,是節點變動,不會改變網絡的映射關係。負載均衡

  三、spread:同一份數據,存儲到不一樣的節點上,換言之就是系統冗餘。一致性哈希致力於下降系統冗度。分佈式

  四、load:負載分散,和balance實際上是差很少的意思,不過這裏更可能是指數據存儲的均衡,balance是指訪的均衡。優化

  Chord算法:
  一致性哈希有多種實現算法,最關鍵的問題在於如何定義數據分割策略和節點快速查詢。編碼

  chord算是最爲經典的實現。cassandra中的DHT,基本是chord的簡化版。spa

  網絡中每一個節點分配一個惟一id,能夠經過機器的mac地址作sha1,是網絡發現的基礎。

  假設整個網絡有N 個節點,而且網絡是呈環狀。兩個節點間的距離定義爲節點間下標差。每一個節點會存儲一張路由表(finger表),表內順時針按照離本節點二、四、八、1六、32.……2i的距離選定log2N個其餘節點的ip信息來記錄,主要是爲了查詢加速。

  存儲:數據被按必定規則切割,每一份數據也有一個獨立id(查詢key),而且和節點id的值域是同樣的。而後查找節點,若是存在和數據id同樣的節點id,則將這份數據存在該節點上;若是不存在,則存儲到離該數據id距離最近的節點上。同時,爲了保證數 據的可靠性,會順時針往下找K個冗餘節點,存儲這份數據。通常認爲K=3是必須的。

  下圖簡單描述了一個chord網絡的部署,綠色節點爲機器,編碼爲hash值。N0節點的finger表能夠看出N0節點的路由規則,其餘節點也有相似的finger表。藍色節點爲數據,根據hash值找到最近的節點並存儲。虛線所指是表示冗餘存儲。

  查詢:先從本身的路由表中,找一個和數據id距離最近、而且存活在網絡中的節點next。若是該節點的 id巧合和數據id相等,那麼恭喜你。若是不相等,則到next進行遞歸查找。通常或須要通過屢次查詢才能找到數據所在的節點,而這個次數是能夠被證實小於等於log2N的。

  在這個查詢的過程當中就體現了路由表的選取優點了,實際上是實現了一個二分查找,從每一個節點來觀察網絡,都是將網絡分紅了log2N塊,最大一塊裏面有N/2個節點。路由表裏面實際上是記錄了每一塊的第一個節點。這樣每一次查詢,最少排除了一半的節點。保證在 log2N次內找到目標節點。

  下圖簡單展現了從N0節點查找N21節點的一個數據的過程,經過finger表通過2跳到達目的地。

  新增一個節點i:須要預先知道網絡中已經存活的一個節點j,而後經過和節點j交互,更新本身和其餘節點的路由表。而且,須要將離本身距離最近的節點中的數據copy過來,以提供數據服務。

  損失一個節點:路由算法會自動跳過這個節點,而且依靠數據的冗餘來持續提供服務。

  KAD算法(Kademlia)
  kad算法實際上是在chord上作的優化。主要是兩個點:
  一、用二進制(32/64/128)表示一個節點的id,兩節點的id異或運算獲得節點間的距離。
  二、 每一個節點保持的路由信息更豐富,一樣是將整個網絡按照劃分紅log2N份,在chord中,是保持log2N個路由節點,但在kad裏面,是保存了 log2N個隊列。每一個隊列長度爲配置值K,記錄網絡中對應節點區域的多個節點,而且根據活躍時間對這些節點進行換入換出。
  第一點是方便進行網絡劃分,節點按照二進制中每一bit的0或1建成一棵二叉樹。

  第二點是使得節點查詢更迅速。從分割狀況咱們就能夠得知,最壞狀況不會差於chord,但保存更多的節點使得命中機率更高。另外隊列中根據活躍時間進行換入換出,更有利於在p2p這種節點變動頻繁的網絡中快速找到有效的節點。

  關於kad的介紹,這篇文章講的比較詳細wenku.baidu.com/view/ee91580216fc700abb68fcae.html

 

  轉自:http://stblog.baidu-tech.com/?p=42

相關文章
相關標籤/搜索