Kademlia協議(模型)是被電驢,BitTorrent所採用了的,基於異或距離算法的分佈式散列表(DHT), 它實現了一個去中心化的信息儲存與查詢系統。算法
Kademlia將網絡設計爲一個具備160層的二叉樹,樹最末端的每一個葉子即是一個節點,節點在樹中的位置由一樣是160bit的節點ID決定。
每一個bit的兩種可能值(0或1), 決定了節點在樹中屬於左面仍是右面的子樹,160層下來,每一個節點ID便都有了一個肯定的位置。網絡
Kademlia使用獨特的異或距離算法來計算節點間的距離,異或是一種簡單的數學計算,它有不少獨特的性質,這些性質在以後會爲咱們帶來方便:分佈式
本身與本身的距離爲0: x ^ x = 0 不一樣的節點間必有距離: x ^ y > 0 交換律,x到y的距離等於y到x的距離: x ^ y = y ^ x 從a經b繞到c, 要比直接從a到c距離長: a ^b + b ^ c >= a ^ c 下面兩個是資料上提到的,彷佛很重要,但我不大理解他們的含義: a + b >= a ^ b (a ^ b) ^ (b ^ c) = a ^ c
在Kademlia中,異或(距離)算法具備單向性(或者說一一對應關係),即給定一個節點和一個距離,一定存在惟一一個相對應節點。包括距離算法在內的,Kademlia中大部分的概念,都既有算術上的意義,又能夠在節點樹上表現實際意義。
事實上,節點間距離反映的就是節點ID中比特的差別狀況,並且越靠前的比特權值越大。或者說是反映節點在樹中相隔了多少個分支,須要向上多少個樹節點才能找到共同的祖先節點。設計
Kademlia中使用了名爲K-桶的概念來儲存其餘(臨近)節點的狀態信息,這裏的狀態信息主要指的就是節點ID, IP, 和端口。
對於160bit的節點ID, 就有160個K-桶,對於每個K-桶i, 它會儲存與本身距離在區間 [2^i, 2^(i+1)) 範圍內的節點的信息,每一個K-桶中儲存有k個其餘節點的信息,在BitTorrent的實現中,k的取值爲8.code
下表反映了每一個K-桶所儲存的信息排序
K-桶 | 儲存的距離區間 | 儲存的距離範圍 | 儲存比率 |
0 | [20, 21) | 1 | 100% |
1 | [21, 22) | 2-3 | 100% |
2 | [22, 23) | 4-7 | 100% |
3 | [23, 24) | 8-15 | 100% |
4 | [24, 25) | 16-31 | 75% |
5 | [25, 26) | 32-63 | 57% |
10 | [210, 211) | 1024-2047 | 13% |
i | [2i, 2i+1) | / | 0.75i-3 |
放在節點樹上,即每一個節點都更傾向於儲存與本身距離近的節點的信息,造成 儲存的離本身近的節點多, 儲存離本身遠的節點少 的局面。
從上表能夠看出,在1-15這個範圍內的節點,只要發現,就會被100%地儲存下來,而離本身距離在1000左右的節點,只會儲存13%.遞歸
對於一個節點而言,K-桶就表明着節點樹上那些未知的節點(其實除了本身都是未知的)構成的子樹,160個K桶分別是具備1到160層的子樹,由小至大。對於節點ID, 160個K-桶分別儲存着節點ID前0到159個bit和本身一致的節點。數學
K-桶中的條目(其餘臨近節點的狀態信息)排序的,每當收到一個消息(如查詢)時,就要更新一次K桶。
首先計算本身與對方的距離,而後儲存到對應的K-桶中,但若是K-桶已滿(前面提到每一個K-桶儲存有k=8個條目), 則會傾向放棄儲存,繼續保持舊的節點信息(若是還有效的話). 除了距離外,Kademlia更傾向於與在線時間長,穩定的節點創建聯繫。
這是由於實踐證實,累積在線時間越長的節點越穩定,越傾向於繼續保持在線,即節點的失效機率和在線時長成反比。
這樣還能夠在必定程度上抵禦攻擊行爲。由於當大量惡意的新節點涌入時,你們都會選擇繼續保持舊的節點信息,而不是接受新的。
除此以外,還須要定時檢查K-桶中的節點是否任然在線,及時刪去已失效節點。it
Kademlia協議僅定義了四種操做:table
當查找一個節點時,首先計算本身與目標節點的距離d, 而後將 log2d 向下取整,找到對應的K-桶,從這個K-桶中選取a個節點(在BitTorrent的實現中取值爲3), 向它們發送查詢。
收到查詢的節點一樣計算距離後從本身的對應K-桶中選取a個節點返回給查詢者。查詢者不斷重複這個過程,知道找到目標節點,或沒法再找到更近的結果。
不少資料將這個過程描述成是遞歸的,但我以爲這裏認爲它是迭代的更爲恰當。
由於每一個節點都更傾向於儲存距本身近的節點的信息,而整個網絡又是一個二叉樹,所以每次查詢都會至少取得距離減半的結果,對於有N個節點的網絡,至多隻須要 log2N 次查詢。
當進行 FIND VALUE 操做時,查詢操做是類型的,每份數據都有一個一樣是160bit的鍵,沒分數據都傾向於儲存在與鍵值距離較近的節點上。
當上傳者上傳一份數據時,上傳者首先定位幾個較爲接近鍵值的節點,用STORE操做要求他們儲存這份數據。
儲存有數據的節點,每當發現比本身與鍵值距離更爲接近的節點時,便將數據複製一份到這個節點上。
當一個新節點欲加入網絡時,只需找到一個已在網絡中的節點,藉助它對本身的節點ID進行一次常規查詢便可,這樣便完成了對本身信息的廣播,讓距本身較近的節點獲知本身的存在。而離開網絡沒必要執行任何操做,一段時間後,你的信息會自動地從其餘節點被刪除。
Kademlia的精妙之處在於它選擇了異或運算做爲計算距離的依據,異或運算不只具備算術的意義,在二叉樹式的網絡模型中,一樣具備實際意義,同時任何狀況下都在強調距離的概念,讓節點間經過距離來聚合起來。