分佈式下載方式(二)DHT分佈式網絡

簡單回顧以下上一篇文章介紹了內容:分佈式下載方式(一)原理分析

分佈式下載方式也有兩種:依賴tracker的“元數據集中,文件數據分散”的方式;另一種是基於分佈式的哈希算法,保證元數據和文件數據完全分開。

在 DHT 網絡裏面,每一個 DHT node 都有一個 ID。這個 ID 是一個很長的串。每個 DHT node 都有責任掌握一些知識,也就是文件索引,或者叫做文件Hash值。每一個DHT node都有一個ID,這個ID是一個160bits(20字節)的數據,它存儲的文件標識也是一個160bits的Hash值。

上面文章我們也介紹了在DHT網絡中我們知道需要聯繫的節點,但是有時候不一定能找到這個節點,但是也可以退而求其次,找到與其相似的節點,那麼這個“相似”怎麼定義?相似不是地理位置的接近,位置近不算近,ID相近或者相似纔是近。這個相似的比較通過異或XOR來處理。舉個例子,兩個節點01010 與 01000 的距離,就是兩個 ID 之間的異或值,爲 00010,也即爲 2。01010 與 00010 的距離爲 01000,也即爲 8,。01010 與 00011 的距離爲 01001,也即 8+1=9 。以此類推,高位不同的,表示距離更遠一些;低位不同的,表示距離更近一些,總的距離爲所有的不同位的距離之和。

如何維護DHT網絡節點

DHT網絡中有很多節點,就像人的朋友圈網絡一樣。朋友圈中的朋友關係有遠近之分,當然DHT中節點之間的關係也有遠近之分,上面也講了如何判斷兩個節點是否相近(或者叫相似)。

DHT網絡的節點是按照層次來劃分的,舉個例子就清楚了。

假設某個節點的 ID 爲 01010,如果一個節點的 ID,前面所有位數都與它相同,只有最後 1 位不同。這樣的節點只有 1 個,爲 01011。與基礎節點的異或值爲 00001,即距離爲 1;對於 01010 而言,這樣的節點歸爲“k-bucket 1”。

如果一個節點的 ID,前面所有位數都相同,從倒數第 2 位開始不同,這樣的節點只有 2 個,即 01000 和 01001,與基礎節點的異或值爲 00010 和 00011,即距離範圍爲 2 和 3;對於 01010 而言,這樣的節點歸爲“k-bucket 2”。我們上面也說了,高位不同的,表示距離更遠一些;低位不同的,表示距離更近一些。

如果一個節點的 ID,前面所有位數相同,從倒數第 i 位開始不同,這樣的節點只有 2^(i-1) 個,與基礎節點的距離範圍爲[2^(i-1), 2^i);對於 01010 而言,這樣的節點歸爲“k-bucket i”。

最終到從倒數 160 位就開始都不同。

你會發現,差距越大,陌生人越多,但是朋友圈不能都放下,所以每一層你可以放N個節點,N要在一定的範圍之內即可。這就是DHT網絡分層的由來。

通過這樣的分層,我們可以將DHT中各個節點之間的遠近關係建立起來,這樣在查找的時候很清晰。那麼問題來了,DHT網絡如何查找節點?

DHT網絡如何查找節點

在DHT網絡分層的基礎上,我們來查找節點,還是舉例子清晰表達一下。

假設,node A 的 ID 爲 00110,要找 node B ID 爲 10000,異或距離爲 10110,距離範圍在[2^4, 2^5),所以這個目標節點可能在“k-bucket 5”中,這就說明 B 的 ID 與 A 的 ID 從第 5 位開始不同,所以 B 可能在“k-bucket 5”中。

然後,A 看看自己的 k-bucket 5 有沒有 B。如果有,太好了,找到你了;如果沒有,在 k-bucket 5 裏隨便找一個 C。因爲是二進制,C、B 都和 A 的第 5 位不同,那麼 C 的 ID 第 5 位肯定與 B 相同,即它與 B 的距離會小於 2^4,相當於比 A、B 之間的距離縮短了一半以上。

再請求 C,在它自己的通訊錄裏,按同樣的查找方式找一下 B。如果 C 知道 B,就告訴 A;如果 C 也不知道 B,那 C 按同樣的搜索方法,可以在自己的通訊錄裏找到一個離 B 更近的 D 朋友(D、B 之間距離小於 2^3),把 D 推薦給 A,A 請求 D 進行下一步查找。

Kademlia 的這種查詢機制,是通過折半查找的方式來收縮範圍,對於總的節點數目爲 N,最多隻需要查詢 log2(N) 次,就能夠找到。

 

上面的圖示就是最壞的一種情況,即使這樣,也還是很快。

A 和 B 每一位都不一樣,所以相差 31,A 找到的朋友 C,不巧正好在中間。和 A 的距離是 16,和 B 距離爲 15,於是 C 去自己朋友圈找的時候,不巧找到 D,正好又在中間,距離 C 爲 8,距離 B 爲 7。於是 D 去自己朋友圈找的時候,不巧找到 E,正好又在中間,距離 D 爲 4,距離 B 爲 3,E 在朋友圈找到 F,距離 E 爲 2,距離 B 爲 1,最終在 F 的朋友圈距離 1 的地方找到 B。當然這是最最不巧的情況,每次找到的朋友都不遠不近,正好在中間。

如果碰巧了,在 A 的朋友圈裏面有 G,距離 B 只有 3,然後在 G 的朋友圈裏面一下子就找到了 B,兩次就找到了。

查找到了節點,那麼如何溝通?

DHT網絡中節點如何溝通?

Kademlia 算法中,每個節點只有 4 個指令:

  • PING:測試一個節點是否在線,還活着沒,相當於打個電話,看還能打通不。
  • STORE:要求一個節點存儲一份數據,既然加入了組織,有義務保存一份數據。
  • FIND_NODE:根據節點 ID 查找一個節點,就是給一個 160 位的 ID,通過上面朋友圈的方式找到那個節點。
  • FIND_VALUE:根據 KEY 查找一個數據,實則上跟 FIND_NODE 非常類似。KEY 就是文件對應的 160 位的 ID,就是要找到保存了文件的節點。

DHT之所以是一個高效的分佈式網絡,說明它是一個動態更新的網絡,網絡節點之間的遠近是動態更新的,如何更新節點信息?

  • 每個 bucket 裏的節點,都按最後一次接觸的時間倒序排列,這就相當於,朋友圈裏面最近聯繫過的人往往是最熟的。
  • 每次執行四個指令中的任意一個都會觸發更新。
  • 當一個節點與自己接觸時,檢查它是否已經在 k-bucket 中,也就是說是否已經在朋友圈。如果在,那麼將它挪到 k-bucket 列表的最底,也就是最新的位置,剛聯繫過,就置頂一下,方便以後多聯繫;如果不在,新的聯繫人要不要加到通訊錄裏面呢?假設通訊錄已滿的情況,PING 一下列表最上面,也即最舊的一個節點。如果 PING 通了,將舊節點挪到列表最底,並丟棄新節點,老朋友還是留一下;如果 PING 不通,刪除舊節點,並將新節點加入列表,這人聯繫不上了,刪了吧。

一個優秀的分佈式網絡,任何節點的加入和離開都不會隨便影響整體網絡的穩定性,這樣纔是一個健壯的分佈式網絡。

小結

  • DHT採用異或來區分遠近,高位不同的,表示距離更遠一些;低位不同的,表示距離更近一些。
  • DHT採用分層的方式將遠近關係層次化。
  • DHT層次的劃分依據,是方便查找節點。最快的利用層次關係來查找節點,查詢的效率是log2(N)
  • DHT更新節點的原則基本上遵照着LRU的方式。

知道了分佈式下載方式的基本原理,接下來了需要一些實踐,如何搭建一個分佈式下載的架構來承載分佈式下載的業務。請繼續關注,稍後會分享。

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