分布式哈希(DHT)
兩個(gè)key point:每個(gè)節(jié)點(diǎn)只維護(hù)一部分路由;每個(gè)節(jié)點(diǎn)只存儲(chǔ)一部分?jǐn)?shù)據(jù)。從而實(shí)現(xiàn)整個(gè)網(wǎng)絡(luò)中的尋址和存儲(chǔ)。
DHT只是一個(gè)概念,提出了這樣一種網(wǎng)絡(luò)模型。并且說(shuō)明它是對(duì)分布式存儲(chǔ)很有好處的。但具體怎么實(shí)現(xiàn),并不是DHT的范疇。
一致性哈希:
DHT的一種實(shí)現(xiàn)。本質(zhì)還是一個(gè)哈希算法。回想平時(shí)我們做負(fù)載均衡,按querystring簽名對(duì)后端節(jié)點(diǎn)取模是最簡(jiǎn)單也是最常用的算法,但節(jié)點(diǎn)的增刪后所造成的問(wèn)題顯而易見(jiàn),原有的請(qǐng)求幾乎都落不到同一臺(tái)機(jī)器上。優(yōu)化一點(diǎn)的是carp算法(用機(jī)器ip和querystring一起做hash,選取hash值最小的一臺(tái)),只讓1/n的數(shù)據(jù)受到影響。
一致性哈希,似乎最早提出是在分布式cache里面的,讓節(jié)點(diǎn)震蕩的時(shí)候,影響最小,以提高分布式cache的命中率。不過(guò)現(xiàn)在更多的應(yīng)用在分布式存儲(chǔ)和p2p系統(tǒng)里面。
一致性哈希也只是提出四個(gè)概念和原則,并沒(méi)有提及具體實(shí)現(xiàn):
1、balance:哈希結(jié)果盡可能的平均分散到各個(gè)節(jié)點(diǎn)上,使得每個(gè)節(jié)點(diǎn)都能得到充分利用。
2、Monotonicity:上面也說(shuō)了,如果是用簽名取模算法,節(jié)點(diǎn)變更會(huì)使得整個(gè)網(wǎng)絡(luò)的映射關(guān)系更改。如果是carp,會(huì)使得1/n的映射關(guān)系更改。一致性哈希的目標(biāo),是節(jié)點(diǎn)變更,不會(huì)改變網(wǎng)絡(luò)的映射關(guān)系。
3、spread:同一份數(shù)據(jù),存儲(chǔ)到不同的節(jié)點(diǎn)上,換言之就是系統(tǒng)冗余。一致性哈希致力于降低系統(tǒng)冗度。
4、load:負(fù)載分散,和balance其實(shí)是差不多的意思,不過(guò)這里更多是指數(shù)據(jù)存儲(chǔ)的均衡,balance是指訪的均衡。
Chord算法:
一致性哈希有多種實(shí)現(xiàn)算法,最關(guān)鍵的問(wèn)題在于如何定義數(shù)據(jù)分割策略和節(jié)點(diǎn)快速查詢。
chord算是最為經(jīng)典的實(shí)現(xiàn)。cassandra中的DHT,基本是chord的簡(jiǎn)化版。
網(wǎng)絡(luò)中每個(gè)節(jié)點(diǎn)分配一個(gè)唯一id,可以通過(guò)機(jī)器的mac地址做sha1,是網(wǎng)絡(luò)發(fā)現(xiàn)的基礎(chǔ)。
假設(shè)整個(gè)網(wǎng)絡(luò)有N 個(gè)節(jié)點(diǎn),并且網(wǎng)絡(luò)是呈環(huán)狀。兩個(gè)節(jié)點(diǎn)間的距離定義為節(jié)點(diǎn)間下標(biāo)差。每個(gè)節(jié)點(diǎn)會(huì)存儲(chǔ)一張路由表(finger表),表內(nèi)順時(shí)針按照離本節(jié)點(diǎn)2、4、8、16、32.……2i的距離選定log2N個(gè)其他節(jié)點(diǎn)的ip信息來(lái)記錄,主要是為了查詢加速。
存儲(chǔ):數(shù)據(jù)被按一定規(guī)則切割,每一份數(shù)據(jù)也有一個(gè)獨(dú)立id(查詢key),并且和節(jié)點(diǎn)id的值域是一樣的。然后查找節(jié)點(diǎn),如果存在和數(shù)據(jù)id一樣的節(jié)點(diǎn)id,則將這份數(shù)據(jù)存在該節(jié)點(diǎn)上;如果不存在,則存儲(chǔ)到離該數(shù)據(jù)id距離最近的節(jié)點(diǎn)上。同時(shí),為了保證數(shù) 據(jù)的可靠性,會(huì)順時(shí)針往下找K個(gè)冗余節(jié)點(diǎn),存儲(chǔ)這份數(shù)據(jù)。一般認(rèn)為K=3是必須的。
下圖簡(jiǎn)單描述了一個(gè)chord網(wǎng)絡(luò)的部署,綠色節(jié)點(diǎn)為機(jī)器,編碼為hash值。N0節(jié)點(diǎn)的finger表可以看出N0節(jié)點(diǎn)的路由規(guī)則,其他節(jié)點(diǎn)也有類似的finger表。藍(lán)色節(jié)點(diǎn)為數(shù)據(jù),根據(jù)hash值找到最近的節(jié)點(diǎn)并存儲(chǔ)。虛線所指是表示冗余存儲(chǔ)。
查詢:先從自己的路由表中,找一個(gè)和數(shù)據(jù)id距離最近、并且存活在網(wǎng)絡(luò)中的節(jié)點(diǎn)next。如果該節(jié)點(diǎn)的 id巧合和數(shù)據(jù)id相等,那么恭喜你。如果不相等,則到next進(jìn)行遞歸查找。一般或需要經(jīng)過(guò)多次查詢才能找到數(shù)據(jù)所在的節(jié)點(diǎn),而這個(gè)次數(shù)是可以被證明小于等于log2N的。
在這個(gè)查詢的過(guò)程中就體現(xiàn)了路由表的選取優(yōu)勢(shì)了,其實(shí)是實(shí)現(xiàn)了一個(gè)二分查找,從每個(gè)節(jié)點(diǎn)來(lái)觀察網(wǎng)絡(luò),都是將網(wǎng)絡(luò)分成了log2N塊,最大一塊里面有N/2個(gè)節(jié)點(diǎn)。路由表里面其實(shí)是記錄了每一塊的第一個(gè)節(jié)點(diǎn)。這樣每一次查詢,最少排除了一半的節(jié)點(diǎn)。保證在 log2N次內(nèi)找到目標(biāo)節(jié)點(diǎn)。
下圖簡(jiǎn)單展示了從N0節(jié)點(diǎn)查找N21節(jié)點(diǎn)的一個(gè)數(shù)據(jù)的過(guò)程,通過(guò)finger表經(jīng)過(guò)2跳到達(dá)目的地。
新增一個(gè)節(jié)點(diǎn)i:需要預(yù)先知道網(wǎng)絡(luò)中已經(jīng)存活的一個(gè)節(jié)點(diǎn)j,然后通過(guò)和節(jié)點(diǎn)j交互,更新自己和其他節(jié)點(diǎn)的路由表。并且,需要將離自己距離最近的節(jié)點(diǎn)中的數(shù)據(jù)copy過(guò)來(lái),以提供數(shù)據(jù)服務(wù)。
損失一個(gè)節(jié)點(diǎn):路由算法會(huì)自動(dòng)跳過(guò)這個(gè)節(jié)點(diǎn),并且依靠數(shù)據(jù)的冗余來(lái)持續(xù)提供服務(wù)。
KAD算法(Kademlia)
kad算法其實(shí)是在chord上做的優(yōu)化。主要是兩個(gè)點(diǎn):
1、用二進(jìn)制(32/64/128)表示一個(gè)節(jié)點(diǎn)的id,兩節(jié)點(diǎn)的id異或運(yùn)算得到節(jié)點(diǎn)間的距離。
2、 每個(gè)節(jié)點(diǎn)保持的路由信息更豐富,同樣是將整個(gè)網(wǎng)絡(luò)按照劃分成log2N份,在chord中,是保持log2N個(gè)路由節(jié)點(diǎn),但在kad里面,是保存了 log2N個(gè)隊(duì)列。每個(gè)隊(duì)列長(zhǎng)度為配置值K,記錄網(wǎng)絡(luò)中對(duì)應(yīng)節(jié)點(diǎn)區(qū)域的多個(gè)節(jié)點(diǎn),并且根據(jù)活躍時(shí)間對(duì)這些節(jié)點(diǎn)進(jìn)行換入換出。
第一點(diǎn)是方便進(jìn)行網(wǎng)絡(luò)劃分,節(jié)點(diǎn)按照二進(jìn)制中每一bit的0或1建成一棵二叉樹(shù)。
第二點(diǎn)是使得節(jié)點(diǎn)查詢更迅速。從分割情況我們就可以得知,最壞情況不會(huì)差于chord,但保存更多的節(jié)點(diǎn)使得命中概率更高。另外隊(duì)列中根據(jù)活躍時(shí)間進(jìn)行換入換出,更有利于在p2p這種節(jié)點(diǎn)變更頻繁的網(wǎng)絡(luò)中快速找到有效的節(jié)點(diǎn)。
關(guān)于kad的介紹,這篇文章講的比較詳細(xì) wenku.baidu.com/view/ee91580216fc700abb68fcae.html
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號(hào)聯(lián)系: 360901061
您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對(duì)您有幫助就好】元
