Chord演算法(原理)

weixin_34162629發表於2015-04-04

Chrod演算法是P2P中的四大演算法之一,是有MIT(麻省理工學院)於2001年提出,其他三大演算法分別是:

Chord的目的是提供一種能在P2P網路快速定位資源的的演算法,Cord並不關心資源是如何儲存的,只是從演算法層面研究資源的取得,因此Chord的API就簡單到只有一個set、get。

1、Chord是什麼?

Chord是一個演算法,也是一個協議。作為一個演算法,Chord可以從數學的角度嚴格證明其正確性和收斂性;作為一個協議,Chord詳細定義了每個環節的訊息型別。當然,Chord之所以受追捧,還有一個主要原因就是Chord足夠簡單,3000行的程式碼就足以實現一個完整的Chord。

Chord還可以被作為一個一致性雜湊、分散式雜湊(DHT)的實現。

2、覆蓋網路(overlaynetwork)

覆蓋網路是指這樣一種網路:構建在其他網路之上、網路節點之間通過虛擬或邏輯連線在一起,比如雲端計算、分散式系統都是覆蓋網路,因為其都構建於TCP/IP之上,且節點之間有聯絡。Chord也是構建於覆蓋網路。

3、結構化與非結構化網路

非結構化的P2P網路是指網路節點之間不存在組織關係,節點之間完全是對等的,比如第一代P2P網路Napster,這類網路結構清晰、簡單,但查詢沒有多大的優化餘地,經常採用全域性或分割槽泛洪查詢,查詢時間長、且結果難以保證(有可能在找到前就超時)。

 

結構化的P2P網路與非結構化恰好相反,我們認為網路在邏輯上存在一個人為設計的結構,比如Chord假定網路是一個環,Kadelima則假定為一顆二叉樹,所有的節點均為樹的葉子節點。有了這些邏輯結構,就給我們資源查詢引入了更多的演算法和思路。

4、分散式雜湊表(DHT)

DHT的主要想法是把網路上資源的存取像Hashtable一樣,可以簡單而快速地進行put、get,該思想的誕生主要是受第一代P2P(Napster)網路的影響。與一致性雜湊相比,DHT更強調的是資源的存取,而不管資源是否是一致性的。與一致性雜湊相同的是,DHT也只是一個概念,具體細節留給各實現。

當前這些P2P實現可以被作為DHT的具體實現,再次再列舉一些有代表性的實現:

  • Chord
  • CAN
  • Tapestry
  • Pastry
  • Apache Cassandra
  • Kadelima
  • P-Grid
  • BitTorrent DHT

5、Chord實現原理

Chord通過把Node和Key對映到相同的空間而保證一致性雜湊,為了保證雜湊的非重複性,Chord選擇SHA-1作為雜湊函式,SHA-1會產生一個2160的空間,每項為一個16位元組(160bit)的大整數。我們可以認為這些整數首尾相連形成一個環,稱之為Chord環。整數在Chord環上按大小順時針排列,Node(機器的IP地址和Port)與Key(資源標識)都被雜湊到Chord環上,這樣我們就假定了整個P2P網路的狀態為一個虛擬的環,因此我們說Chord是結構化的P2P網路。

 

下面有幾個定義:

  • 我們稱Chord環上的每個節點為標誌符
  • 如果某個Node對映到了某個標誌符,則繼續稱該標準符為Node
  • 按順時針,節點前面的成為前繼(predecessor),節點後面的成為後繼(successor);同理,第一個predecessor稱之為直接前繼,第一個successor稱之為直接後繼

如圖:

紅色點為Node,藍色為標誌符。上面只是部分節點和標誌符,以節點N1為例說明其Finger表中的successor:

 

No ith successor Successor
1 N1+20  N18 
2 N1+21  N18
3 N1+22  N18
4 N1+23  N18
5 N1+24  N18
6 N1+25  N45
7 N1+26   N1
8 N1+27  N1

 

把Node和Key都對映到一個值域感覺是把狗和貓放在一起衡量,雖然有點怪,但這樣可以保證一致性雜湊,具體可以參考前文。

 

很顯然,分佈在Chord環上的Node數遠遠小於標誌符數(2160是一個無法衡量的天文數字),這樣Chord環上的Node就會很稀疏地分佈在Chord環上,理論上應該是隨機分佈,但如前面一致性雜湊的討論,如果節點數量不多,分佈肯定是不均勻的,可以考慮增加虛擬節點來增加其平衡性,如果在節點較多(比如大型的P2P網路有上百萬的機器)就不必引入虛擬節點。

 

很顯然,任何查詢只要沿Chord環一圈結果肯定可以找到,這樣的時間複雜度是O(N),N為網路節點數,但對一個上百萬節點,且節點經常加入、退出的P2P網路來說,O(N)是不可忍受的,因此Chord提出了下面非線性查詢的演算法:

  1. 每個節點都維護一個Finger表,該表長度為m(m就是位數,在Chord中為160),該表的第i項存放節點n的第(n+2i-1) mod 2m個successor(1<=i<=m)
  2. 每個節點都維護一個predecessor和successor列表,該列表的作用是能快速定位前繼和後繼,並能週期性檢測前繼和後繼的健康狀態
  3. 就是說存放的successor是按2的倍數等比遞增,自所以取模是因為最後的節點的successor是開始的幾個節點,比如最大的一個節點的下一個節點定義為第一個節點
  4. 資源Key儲存在下面的Node上:沿Chord環,hash(Node)>=hash(key)的第一個Node,我們稱這個Node為這個Key的successor
  5. 給定一個Key,按下面的步驟查詢其對應的資源位於哪個節點,也就是查詢該Key的successor:(假如查詢是在節點n上進行)
  • 檢視Key的雜湊是否落在節點n和其直接successor之間,若是結束查詢,n的successor即為所找
  • 在n的Finger表中,找出與hash(Key)距離最近且<hash(Key)的n的successor,該節點也是Finger表中最接近Key的predecessor,把查詢請求轉發到該節點
  • 繼續上述過程,直至找到Key對應的節點

從直覺上來說,上次查詢過程應該是指數收斂的,類似二分法的查詢,收斂速度應該是很快的;反過來,查詢時間或路由複雜度應該是對數即的,在下面我們會證明這一點。

 

下圖表明瞭節點N1查詢節點N53的過程,還是非常快的:

 

6、Chord收斂性證明

對一個演算法而言,收斂性是至關重要的,如果沒有收斂性做保證,在程式上化再多的心思也是徒勞。在證明之前,我們再強調3點:

  • Key存放在Key的successor節點上(滿足:hash(Node)>=hash(Key))
  • 節點n的第i項存放的是第(n+2i-1)個successor
  • 查詢是根據最近原則,當前節點沒有存放Key則從Finger表中尋找與hash(Key)距離最近的Node繼續這個過程

這裡要區分是Key的successor還是節點n的successor,同時要注意最近匹配原則。

 

假如節點n的Finger表中的第i個successor與Key的距離最近,則滿足:Key處在第i項與第i+1項中間

記第i項為J,第i+1項為P

  • J<hash(Key)
  • P>hash(Key)

而:

J = n + 2i-1

P = n + 2i

節點n與Key的距離應該處在n與J和P的中間,即 J-n<n - hash(Key)<P - n

 

(1) 2i-1<n - hash(Key)<2i

(2) 而J與Key的距離最大為J與P的距離 J-hash(Key) <P - J = 2i-1

也就是說J與Key的距離,小於n與Key的距離,並且該距離小於n與Key距離的一半,這樣我們保證每次迭代,與Key的距離都會收斂,並且至少按2的指數收斂,也就是折半查詢。

 

至此,我們理論證明了Chord的收斂性。

 

7、深入Chord演算法

其實Chord演算法可以完全轉換為一個數學問題:

在Chord環上任意標記個點作為Node集合,任意指定Node T,從任意的Node N開始根據Chord查詢演算法都能找到節點T。

 

為什麼能這麼轉換呢?因為只要找到了Key的直接前繼,也就算找到了Key,所有問題轉化為一個在Chord環上通過Node找Node的問題。這樣,這個題就馬上變的很神奇,假如我們把查詢的步驟記錄為路徑,又轉化為任意2個節點之間存在一條最短路徑,而Chord演算法其實就是構造了這樣一條最短路徑,那這樣的路徑會不會不存在呢?不會的,因為Chord本身是一個環,最差情況可以通過線性查詢保證其收斂性。

 

從最短路徑的角度來看,Chord只是對已存線上性路徑的改進,根據這個思路,我們完全可以設計出其他的最短路徑演算法。從演算法本來來看,保證演算法收斂或正確性的前提是每個Node要正確地維護其後繼節點,但在一個大型的P2P網路中,會有節點的頻繁加入、退出,如果沒有額外的工作,很難保證每個節點有正確的後繼。

 

Chord冗餘性:

所謂冗餘性是指Chord的Finger表中存在無用項,那些處在Node N和其successor之間的項均無意義,因為這些項所代表的successor不存在。比如在N1的Finger表中的第1~5項均不存在,故都指向了N18,至少第1~4項為冗餘資訊。

一般說來,假如Chord環的大小為2m,節點數為2n,假如節點平均分佈在Chord環上,則任一節點N的Finger表中的第i項為冗餘的條件為:N+2i-1<N + 2m/2n =>2i-1<2m-n =>i <m-n+1,即當i <m-n+1時才有冗餘。

冗餘度為:(m-n+1)/m=1-(n-1)/m,一般說來m >>n,所以Chord會存在很多的冗餘資訊。假如,網路上有1024個節點,即n=10,則冗餘度為:1-(10-1)/160≈94%。所以很多論文都指出這一點,並認為會造成冗餘查詢,降低效能。其實不然,因為這些冗餘資訊是分佈在多個Node的Finger表,如果採取適當的路由演算法,對路由計算不會有任何影響。

 

至此,我們已經完整地討論了Chord演算法及其核心思想,接下來要討論的是Chord的具體實施。

http://blog.csdn.net/chen77716/article/details/6059575

相關文章