分佈式哈希表原理與實現(Python版和Java版)

 

 

本文介紹了布隆過濾器的概念及變體,這種描述很是適合代碼模擬實現。重點在於標準布隆過濾器和計算布隆過濾器,其餘的大都在此基礎上優化。文末附上了標準布隆過濾器和計算布隆過濾器的代碼實現(Java版和Python版)node

本文內容皆來自 《Foundations of Computers Systems Research》一書,本身翻譯的,轉載請註明出處,不許確的部分請告知,歡迎討論。算法

 

什麼是分佈式哈希表?

 

    分佈式哈希表是一個基本的結構,被普遍的應用在許多分佈式系統中,用於組織動態改變的(分佈式)節點集合和透明的資源定位服務,如,DHT 在許多 P2P 系統中做爲一個基本結構提供高效透明的資源定位服務。全部節點都同等重要,這使得 DHT 更加的裝載平橫。並且,在 DHT 中具備必定規律的拓撲結構(環、樹、超立方體、網格、蝴蝶形……),這使得查找更加的高效。雖然,各類 DHT 實現的拓撲結構各不相同,但它們至少提供如下兩個基本的功能:
  • put(key, value): 插入一個鍵值對到 DHT 網絡中,不須要知道具體的存儲地點
  • value = get(key):根據 key 從 DHT 網絡中檢索相應的值,不須要知道具體的存儲地點

 

DHT 網絡設計的重點大多在如下幾個方面:
  • 拓撲結構(Topology structure)
  • 路由協議(Routing protocol)
  • 動態維護和失敗恢復(Dynamic maintenance and failure recovery)

 

 

各類 DHT 對比

DHTs Topology Node Degree Routing Hops
CAN mesh O(d) O(dn^(1/d))
Chord ring O(logn) O(logn)
Pastry tree + ring O(logn) O(logn)
Tapestry tree O(logn) O(logn)
Kademlia tree O(logn) O(logn)
Viceroy butterfly 7 O(logn)
Koord de Bruijn graph + ring 2 or O(logn) O(logn) or O(logn/loglogn)
Cycloid hypecube + ring O(d) with n = d2^d

 

一個 DHT 例子 —— Chord


Chord 的拓撲結構

  • Chord 使用一致性哈希(consistent hashing)將鍵(key)和節點(node)映射成一個 m 位的標識符
  • Chord 使用環形做爲它的拓撲結構,節點按照順時針,標識符遞增排列。所以,每個節點都有一個直接前驅和一個直接後繼。
  • 每個節點負責存儲標識符範圍爲(i-1, i] 的鍵。i 爲節點的標識符,i-1 爲當前節點前驅節點的標識符。
拓撲結構如右圖。N14 節點負責存儲標識符爲(9,10,11,12,13,14)的鍵
 
             

Chord 的查找算法

    如果使用普通的遍歷查找,那麼每一個節點的度爲1(只有後繼),查找的時間複雜度爲log(n)。而 chord 在節點度數和時間複雜度之間作了個折中:增長節點的度,減小查找時間。
    每一個節點都有一個 finger table,該表有 m 個條目,每一個條目指向另外的節點。條目指向的節點計算公式爲:(n + 2^k) % 2^m 。(n 爲當前節點的標識符,m 是標識符空間的位數,0 <= k < m)。如右圖。
    爲何要設置這樣一個指向表呢?爲了更快的查找。假設如今咱們要從節點 n 開始,查找標識符 id。因而有以下的步驟:
  • 計算當前節點 n 到目標節點(存儲 id)的距離:d = (id-n+2^m) % 2^m,從這裏能夠知道:(n + d) % 2^m = id
  • 而後計算最大的 k,使得 2^k <= d。而後根據 finger table,跳轉到存儲標識符 n + 2^k 的節點。如今離目標又近了一步
  • 以上過程遞歸執行,直到目標標識符位於當前節點和其直接後繼之間,那麼此時目標標識符就存儲在當前節點的直接後繼中
 


Chord 的動態維護和失敗節點恢復
網絡

    在分佈式系統中,會常常的進行節點的動態加入和離開,並且節點也可能出問題,因此還須要考慮節點的動態維護,一些算法就要週期的執行來維護拓撲結構。舉一個例子,節點 N26 加入該網絡:併發

  • 節點 N26 向節點 n 請求加入網絡
  • n 會找到爲標識符 26 負責的節點 N32,N32 就是 N26 的直接後繼
  • 節點 N26 會修改本身的後繼,指向 N32,而後執行一個算法更新後繼,而且給新後繼 N32 發送一條問候信息
  • N32 收到該消息後,發現 N26 離本身比當前前驅 N21 更近,因此,N32 就會重設它的前驅爲 N26
  • N21 執行一個算法更新後繼,發現 N26 是本身的新後繼,因而修改指向,併發送問候信息給 N26
  • N26 收到消息後,發現本身的前驅爲空,而後重設本身的前驅爲 N21
上面的過程可以很好的處理節點的加入,但當節點出了問題時,就很可貴知其後繼節點信息,所以,Chord 還維護了一張後繼信息表,但不是記錄全部節點的,表長爲 r = log(N),當節點出問題後,可以有較大機率獲取正確的後繼節點信息。
 

學習案例(待更新)


案例一:協同域名系統(Cooperative Domain Name System,CoDoNS)




案例二:協同文件系統(Cooperative File System,CFS)



 

代碼實現(待更新)

相關文章
相關標籤/搜索