易懂分布式 | Kademlia算法

近年來,區(qū)塊鏈技術(shù)(部分人更愿意稱之為分布式賬本技術(shù))的走紅將分布式技術(shù)的概念帶入大眾的視野。區(qū)塊鏈技術(shù)之所以備受追捧,一方面是其展現(xiàn)了一種在計(jì)算機(jī)的輔助下,人類可以以無中心、無權(quán)威、無層級的方式來進(jìn)行社會協(xié)作的美妙前景;另一方面,從物理上可論證,分布式的簡單協(xié)議,比中心化的復(fù)雜協(xié)議更為高效。分布式技術(shù)似乎能夠在帶來公平的同時(shí),還帶來效率。

要理解分布式技術(shù)并不困難,因?yàn)榉植际郊夹g(shù)并不高深,但其設(shè)計(jì)上往往巧妙得令人拍手稱贊。

本文介紹一種常見而巧妙的分布式技術(shù),Kademlia算法。


Kademlia算法是一種分布式存儲及路由的算法。什么是分布式存儲?試想一下,一所1000人的學(xué)校,現(xiàn)在學(xué)校突然決定拆掉圖書館(不設(shè)立中心化的服務(wù)器),將圖書館里所有的書都分發(fā)到每位學(xué)生手上(所有的文件分散存儲在各個(gè)節(jié)點(diǎn)上)。即是所有的學(xué)生,共同組成了一個(gè)分布式的圖書館。

由中心圖書館到分布式圖書館

在這種場景下,有幾個(gè)關(guān)鍵的問題需要回答。

1)關(guān)鍵問題

  1. 每個(gè)同學(xué)手上都分配哪些書。即如何分配存儲內(nèi)容到各個(gè)節(jié)點(diǎn),新增/刪除內(nèi)容如何處理。
  2. 當(dāng)你需要找到一本書,譬如《分布式算法》的時(shí)候,如何知道哪位同學(xué)手上有《分布式算法》(對1000個(gè)人挨個(gè)問一遍,“你有沒有《分布式算法》?”,顯然是個(gè)不經(jīng)濟(jì)的做法),又如何聯(lián)系上這位同學(xué)。即一個(gè)節(jié)點(diǎn)如果想獲取某個(gè)特定的文件,如何找到存儲文件的節(jié)點(diǎn)/地址/路徑。
如何尋找需要的書籍?

接下來,讓我們來看看Kademlia算法如何巧妙地解決這些問題。

2)節(jié)點(diǎn)的要素

首先我們來看看每個(gè)同學(xué)(節(jié)點(diǎn))都有哪些屬性:

  • 學(xué)號(Node ID,2進(jìn)制,160位)
  • 手機(jī)號碼(節(jié)點(diǎn)的IP地址及端口)

每個(gè)同學(xué)會維護(hù)以下內(nèi)容:

  • 從圖書館分發(fā)下來的書本(被分配到需要存儲的內(nèi)容),每本書當(dāng)然都有書名和書本內(nèi)容(內(nèi)容以<key, value>對的形式存儲,可以理解為文件名和文件內(nèi)容);
  • 一個(gè)通訊錄,包含一小部分其他同學(xué)的學(xué)號和手機(jī)號,通訊錄按學(xué)號分層(一個(gè)路由表,稱為“k-bucket”,按Node ID分層,記錄有限個(gè)數(shù)的其他節(jié)點(diǎn)的ID和IP地址及端口)。

根據(jù)上面那個(gè)類比,可以看看這個(gè)表格:

概念對比

(Hash的概念解釋,可參見百度百科-哈希算法

關(guān)于為什么不是每個(gè)同學(xué)都有全量通訊錄(每個(gè)節(jié)點(diǎn)都維護(hù)全量路由信息):其一,分布式系統(tǒng)中節(jié)點(diǎn)的進(jìn)入和退出是相當(dāng)頻繁的,每次有變動(dòng)時(shí)都全網(wǎng)廣播通訊錄更新,通訊量會很大;其二,一旦任意一個(gè)同學(xué)被壞人綁架了(節(jié)點(diǎn)被黑客攻破),則壞人馬上就擁有了所有人的手機(jī)號碼,這并不安全。

3)文件的存儲及查找

原來收藏在圖書館里,按索引號碼得整整齊齊的書,以一種什么樣的方式分發(fā)到同學(xué)們手里呢?大致的原則,包括:1)書本能夠比較均衡地分布在同學(xué)們的手里,不會出現(xiàn)部分同學(xué)手里書特別多、而大部分同學(xué)連一本書都沒有的情況;2)同學(xué)想找一本特定的書的時(shí)候,能夠一種相對簡單的索引方式找到這本書。
Kademlia作了下面這種安排:
假設(shè)《分布式算法》這本書的書名的hash值是 00010000,那么這本書就會被要求存在學(xué)號為00010000的同學(xué)手上。(這要求hash算法的值域與node ID的值域一致。Kademlia的Node ID是160位2進(jìn)制。這里的示例對Node ID進(jìn)行了簡略)
但還得考慮到會有同學(xué)缺勤。萬一00010000今天沒來上學(xué)(節(jié)點(diǎn)沒有上線或徹底退出網(wǎng)絡(luò)),那《分布式算法》這本書豈不是誰都拿不到了?那算法要求這本書不能只存在一個(gè)同學(xué)手上,而是被要求同時(shí)存儲在學(xué)號最接近00010000的k位同學(xué)手上,即000100010001001000010011…等同學(xué)手上都會有這本書。

同樣地,當(dāng)你需要找《分布式算法》這本書時(shí),將書名hash一下,得到 00010000,這個(gè)便是索書號,你就知道該找哪(幾)位同學(xué)了。剩下的問題,就是找到這(幾)位同學(xué)的手機(jī)號。

書籍搜索定位

4)節(jié)點(diǎn)的異或距離

由于你手上只有一部分同學(xué)的通訊錄,你很可能并沒有00010000的手機(jī)號(IP地址)。那如何聯(lián)系上目標(biāo)同學(xué)呢?

通訊錄上并沒有目標(biāo)同學(xué)的情況

一個(gè)可行的思路就是在你的通訊錄里找到一位擁有目標(biāo)同學(xué)的聯(lián)系方式的同學(xué)。前面提到,每位同學(xué)手上的通訊錄都是按距離分層的。算法的設(shè)計(jì)是,如果一個(gè)同學(xué)離你越近,你手上的通訊錄里存有ta的手機(jī)號碼的概率越大。而算法的核心的思路就可以是:當(dāng)你知道目標(biāo)同學(xué)Z與你之間的距離,你可以在你的通訊錄上先找到一個(gè)你認(rèn)為與同學(xué)Z最相近的同學(xué)B,請同學(xué)B再進(jìn)一步去查找同學(xué)Z的手機(jī)號。

上文提到的距離,是學(xué)號(Node ID)之間的異或距離(XOR distance)。異或是針對yes/no或者二進(jìn)制的運(yùn)算.

異或的運(yùn)算法則為:0⊕0=0,1⊕0=1,0⊕1=1,1⊕1=0(同為0,異為1)
百度百科-異或

舉2個(gè)例子:
0101000001010010距離(即是2個(gè)ID的異或值)為00000010(換算為十進(jìn)制即為2);
0100000000000001距離為01000001(換算為十進(jìn)制即為26+1,即65);
如此類推。

那通訊錄是如何按距離分層呢?下面的示例會告訴你,按異或距離分層,基本上可以理解為按位數(shù)分層。設(shè)想以下情景:
0000110為基礎(chǔ)節(jié)點(diǎn),如果一個(gè)節(jié)點(diǎn)的ID,前面所有位數(shù)都與它相同,只有最后1位不同,這樣的節(jié)點(diǎn)只有1個(gè)——0000111,與基礎(chǔ)節(jié)點(diǎn)的異或值為0000001,即距離為1;對于0000110而言,這樣的節(jié)點(diǎn)歸為“k-bucket 1”
如果一個(gè)節(jié)點(diǎn)的ID,前面所有位數(shù)相同,從倒數(shù)第2位開始不同,這樣的節(jié)點(diǎn)只有2個(gè):00001010000100,與基礎(chǔ)節(jié)點(diǎn)的異或值為00000110000010,即距離范圍為3和2;對于0000110而言,這樣的節(jié)點(diǎn)歸為“k-bucket 2”
……
如果一個(gè)節(jié)點(diǎn)的ID,前面所有位數(shù)相同,從倒數(shù)第n位開始不同,這樣的節(jié)點(diǎn)只有2(i-1)個(gè),與基礎(chǔ)節(jié)點(diǎn)的距離范圍為[2(i-1), 2i);對于0000110而言,這樣的節(jié)點(diǎn)歸為“k-bucket i”

按位數(shù)區(qū)分k-bucket

對上面描述的另一種理解方式:如果將整個(gè)網(wǎng)絡(luò)的節(jié)點(diǎn)梳理為一個(gè)按節(jié)點(diǎn)ID排列的二叉樹,樹最末端的每個(gè)葉子便是一個(gè)節(jié)點(diǎn),則下圖就比較直觀的展現(xiàn)出,節(jié)點(diǎn)之間的距離的關(guān)系。


k-bucket示意圖:右下角的黑色實(shí)心圓,為基礎(chǔ)節(jié)點(diǎn)(按wiki百科的配圖修改)

回到我們的類比。每個(gè)同學(xué)只維護(hù)一部分的通訊錄,這個(gè)通訊錄按照距離分層(可以理解為按學(xué)號與自己的學(xué)號從第幾位開始不同而分層),即k-bucket1, k-bucket 2, k-bucket 3…雖然每個(gè)k-bucket中實(shí)際存在的同學(xué)人數(shù)逐漸增多,但每個(gè)同學(xué)在它自己的每個(gè)k-bucket中只記錄k位同學(xué)的手機(jī)號(k個(gè)節(jié)點(diǎn)的地址與端口,這里的k是一個(gè)可調(diào)節(jié)的常量參數(shù))。
由于學(xué)號(節(jié)點(diǎn)的ID)有160位,所以每個(gè)同學(xué)的通訊錄中共分160層(節(jié)點(diǎn)共有160個(gè)k-bucket)。整個(gè)網(wǎng)絡(luò)最多可以容納2^160個(gè)同學(xué)(節(jié)點(diǎn)),但是每個(gè)同學(xué)(節(jié)點(diǎn))最多只維護(hù)160 * k 行通訊錄(其他節(jié)點(diǎn)的地址與端口)。

5)節(jié)點(diǎn)定位

我們現(xiàn)在來闡述一個(gè)完整的索書流程。

A同學(xué)(學(xué)號00000110)想找《分布式算法》,A首先需要計(jì)算書名的哈希值,hash(《分布式算法》) = 00010000。那么A就知道ta需要找到00010000號同學(xué)(命名為Z同學(xué))或?qū)W號與Z鄰近的同學(xué)。
Z的學(xué)號00010000與自己的異或距離為 00010110,距離范圍在[24, 25),所以這個(gè)Z同學(xué)可能在k-bucket 5中(或者說,Z同學(xué)的學(xué)號與A同學(xué)的學(xué)號從第5位開始不同,所以Z同學(xué)可能在k-bucket 5中)。
然后A同學(xué)看看自己的k-bucket 5有沒有Z同學(xué):

  • 如果有,那就直接聯(lián)系Z同學(xué)要書;
  • 如果沒有,在k-bucket 5里隨便找一個(gè)B同學(xué)(注意任意B同學(xué),它的學(xué)號第5位肯定與Z相同,即它與Z同學(xué)的距離會小于24,相當(dāng)于比Z、A之間的距離縮短了一半以上),請求B同學(xué)在它自己的通訊錄里按同樣的查找方式找一下Z同學(xué):
    -- 如果B知道Z同學(xué),那就把Z同學(xué)的手機(jī)號(IP Address)告訴A;
    -- 如果B也不知道Z同學(xué),那B按同樣的搜索方法,可以在自己的通訊錄里找到一個(gè)離Z更近的C同學(xué)(Z、C之間距離小于23),把C同學(xué)推薦給A;A同學(xué)請求C同學(xué)進(jìn)行下一步查找。
查詢方式示意

Kademlia的這種查詢機(jī)制,有點(diǎn)像是將一張紙不斷地對折來收縮搜索范圍,保證對于任意n個(gè)學(xué)生,最多只需要查詢log2(n)次,即可找到獲得目標(biāo)同學(xué)的聯(lián)系方式(即在對于任意一個(gè)有[2(n?1), 2n)個(gè)節(jié)點(diǎn)的網(wǎng)絡(luò),最多只需要n步搜索即可找到目標(biāo)節(jié)點(diǎn))。

每次搜索都將距離至少收縮一半

以上便是Kademlia算法的基本原理。以下再簡要介紹協(xié)議中的技術(shù)細(xì)節(jié)。

6)算法的三個(gè)參數(shù):keyspace,k和α

  • keyspace
    -- 即ID有多少位
    -- 決定每個(gè)節(jié)點(diǎn)的通訊錄有幾層
  • k
    -- 每個(gè)一層k-bucket里裝k個(gè)node的信息,即<node ID, IP Adress, port>
    -- 每次查找node時(shí),返回k個(gè)node的信息
    -- 對于某個(gè)特定的data,離其key最近的k個(gè)節(jié)點(diǎn)被會要求存儲這個(gè)data
  • α
    -- 每次向其他node請求查找某個(gè)node時(shí),會向α個(gè)node發(fā)出請求

7)節(jié)點(diǎn)的指令

Kademlia算法中,每個(gè)節(jié)點(diǎn)只有4個(gè)指令

  • PING
    -- 測試一個(gè)節(jié)點(diǎn)是否在線
  • STORE
    -- 要求一個(gè)節(jié)點(diǎn)存儲一份數(shù)據(jù)
  • FIND_NODE
    -- 根據(jù)節(jié)點(diǎn)ID查找一個(gè)節(jié)點(diǎn)
  • FIND_VALUE
    -- 根據(jù)KEY查找一個(gè)數(shù)據(jù),實(shí)則上跟FIND_NODE非常類似

8)k-bucket的維護(hù)及更新機(jī)制

  • 每個(gè)bucket里的節(jié)點(diǎn)都按最后一次接觸的時(shí)間倒序排列
  • 每次執(zhí)行四個(gè)指令中的任意一個(gè)都會觸發(fā)更新
  • 當(dāng)一個(gè)節(jié)點(diǎn)與自己接觸時(shí),檢查它是否在K-bucket中
    -- 如果在,那么將它挪到k-bucket列表的最底(最新)
    -- 如果不在,PING一下列表最上面(最舊)的一個(gè)節(jié)點(diǎn)
    -- a) 如果PING通了,將舊節(jié)點(diǎn)挪到列表最底,并丟棄新節(jié)點(diǎn)
    -- b) 如果PING不通,刪除舊節(jié)點(diǎn),并將新節(jié)點(diǎn)加入列表

該機(jī)制保證了任意節(jié)點(diǎn)加入和離開都不影響整體網(wǎng)絡(luò)。

9)總結(jié)

Kademlia是分布式哈希表(Distributed Hash Table, DHT)的一種。而DHT是一類去中心化的分布式系統(tǒng)。在這類系統(tǒng)中,每個(gè)節(jié)點(diǎn)(node)分別維護(hù)一部分的存儲內(nèi)容以及其他節(jié)點(diǎn)的路由/地址,使得網(wǎng)絡(luò)中任何參與者(即節(jié)點(diǎn))發(fā)生變更(進(jìn)入/退出)時(shí),對整個(gè)網(wǎng)絡(luò)造成的影響最小。DHT可以用于構(gòu)建更復(fù)雜的應(yīng)用,包括分布式文件系統(tǒng)、點(diǎn)對點(diǎn)技術(shù)文件分享系統(tǒng)、合作的網(wǎng)頁高速緩存、域名系統(tǒng)以及實(shí)時(shí)通信等。
Kademlia算法在2002年由Petar Maymounkov 和 David Mazières 所設(shè)計(jì),以異或距離來對哈希表進(jìn)行分層是其特點(diǎn)。Kademlia后來被eMule、BitTorrent等P2P軟件采用作為底層算法。Kademlia可以作為信息安全技術(shù)的奠基之一。
Kademlia的優(yōu)點(diǎn)在于:

  • 對于任意一個(gè)有[ 2(n?1) ,2??)個(gè)節(jié)點(diǎn)的網(wǎng)絡(luò),最多只需要n步搜索即可找到目標(biāo)節(jié)點(diǎn);
  • K-bucket的更新機(jī)制一定程度上保持了網(wǎng)絡(luò)的活性和安全性。

參考文獻(xiàn)
wiki百科-分布式哈希表
wiki百科-Kademlia
Kademlia: A Peer-to-peer information system based on the XOR Metric
王子亭的Kademlia筆記
韓鋒.《區(qū)塊鏈的人工智能》.新星出版社《區(qū)塊鏈新經(jīng)濟(jì)藍(lán)圖及導(dǎo)讀》的譯后注

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,936評論 6 535
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,744評論 3 421
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,879評論 0 381
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,181評論 1 315
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,935評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,325評論 1 324
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,384評論 3 443
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,534評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,084評論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,892評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,067評論 1 371
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,623評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,322評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,735評論 0 27
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,990評論 1 289
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,800評論 3 395
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,084評論 2 375

推薦閱讀更多精彩內(nèi)容