Dynamo的意思是發(fā)電機,顧名思義,這一整套的方案都像發(fā)電機一樣,源源不斷地提供服務(wù),永不間斷。以下內容看上去有點(diǎn)教條,但基本上如果你要理解原理,這每一項都是必須知道的。

圖一:CAP原則當年的PPT
Consistency(一致性):即數據一致性,簡(jiǎn)單的說(shuō),就是數據復制到了N臺機器,如果有更新,要N機器的數據是一起更新的。
Availability(可用性):好的響應性能,此項意思主要就是速度。
Partition tolerance(分區容錯性):這里是說(shuō)好的分區方法,體現具體一點(diǎn),簡(jiǎn)單地可理解為是節點(diǎn)的可擴展性。
定理:任何分布式系統只可同時(shí)滿(mǎn)足二點(diǎn),沒(méi)法三者兼顧。
忠告:架構師不要將精力浪費在如何設計能滿(mǎn)足三者的完美分布式系統,而是應該進(jìn)行取舍。
DHT(Distributed Hash Table,分布式哈希表),它是一種分布式存儲尋址方法的統稱(chēng)。就像普通的哈希表,里面保存了key與value的對應關(guān)系,一般都能根據一個(gè)key去對應到相應的節點(diǎn),從而得到相對應的value。
這里隨帶一提,在DHT算法中,一致性哈希作為第一個(gè)實(shí)用的算法,在大多數系統中都使用了它。一致性哈?;窘鉀Q了在P2P環(huán)境中最為關(guān)鍵的問(wèn)題 ——如何在動(dòng)態(tài)的網(wǎng)絡(luò )拓撲中分布存儲和路由。每個(gè)節點(diǎn)僅需維護少量相鄰節點(diǎn)的信息,并且在節點(diǎn)加入/退出系統時(shí),僅有相關(guān)的少量節點(diǎn)參與到拓撲的維護中。至于一致性哈希的細節就不在這里詳細說(shuō)了,要指明的一點(diǎn)是,在Dynamo的數據分區方式之后,其實(shí)內部已然是一個(gè)對一致性哈希的改造了。
有了上面一章里的兩個(gè)基礎介紹之后,我們開(kāi)始進(jìn)入Dynamo的世界。
在Dynamo的實(shí)現中提到一個(gè)關(guān)鍵的東西,就是數據分區。 假設我們的數據的key的范圍是0到2的64次方(不用懷疑你的數據量會(huì )超過(guò)它,正常甚至變態(tài)情況下你都是超不過(guò)的,甚至像伏地魔等其他類(lèi)Dynamo系統是使用的 2的32次方),然后設置一個(gè)常數,比如說(shuō)1000,將我們的key的范圍分成1000份。然后再將這1000份key的范圍均勻分配到所有的節點(diǎn)(s個(gè)節點(diǎn)),這樣每個(gè)節點(diǎn)負責的分區數就是1000/s份分區。

圖二:三個(gè)節點(diǎn)分12個(gè)區的數據的情況
因為數據是均勻離散到這個(gè)環(huán)上的(有人開(kāi)始會(huì )認為數據的key是從1、2、3、4……這樣子一直下去的,其實(shí)不是的,哈希計算出來(lái)的值,都是一個(gè)離散的結果),所以我們每個(gè)分區的數據量是大致相等的。從圖上我們可以得出,每臺機器都分到了三個(gè)分區里的數據,并且因為分區是均勻的,在分區數量是相當大的時(shí)候,數據的分布會(huì )更加的均勻,與此同時(shí),負載也被均勻地分開(kāi)了(當然了,如果硬要說(shuō)你的負載還是只集中在一個(gè)分區里,那就不是在這里要討論的問(wèn)題了,有可能是你的哈希函數是不是有什么樣的問(wèn)題了)。

圖三:加入一個(gè)新的節點(diǎn)D的情況
同樣是圖二里的情況,12個(gè)分區分到ABC三個(gè)節點(diǎn),圖三中就是再進(jìn)入了一個(gè)新的節點(diǎn)D,從圖上的重新分布情況可以得出,所有節點(diǎn)里只需要轉移四分之一的數據到新來(lái)的節點(diǎn)即可,同時(shí),新節點(diǎn)的負載也伴隨分區的轉移而轉移了(這里的12個(gè)分區太少了,如果是1200個(gè)分區甚至是12000個(gè)分區的話(huà),這個(gè)結論就是正確的了,12個(gè)分區只為演示用)。
在Dynamo系統中,第一次提出來(lái)了NRW的方法。
N:復制的次數;
R:讀數據的最小節點(diǎn)數;
W:寫(xiě)成功的最小分區數。
這三個(gè)數的具體作用是用來(lái)靈活地調整Dynamo系統的可用性與一致性。
舉個(gè)例子來(lái)說(shuō),如果R=1的話(huà),表示最少只需要去一個(gè)節點(diǎn)讀數據即可,讀到即返回,這時(shí)是可用性是很高的,但并不能保證數據的一致性,如果說(shuō)W同時(shí)為1的 話(huà),那可用性更新是最高的一種情況,但這時(shí)完全不能保障數據的一致性,因為在可供復制的N個(gè)節點(diǎn)里,只需要寫(xiě)成功一次就返回了,也就意味著(zhù),有可能在讀的這一次并沒(méi)有真正讀到需要的數據(一致性相當的不好)。如果W=R=N=3的話(huà),也就是說(shuō),每次寫(xiě)的時(shí)候,都保證所有要復制的點(diǎn)都寫(xiě)成功,讀的時(shí)候也是都讀到,這樣子讀出來(lái)的數據一定是正確的,但是其性能大打折扣,也就是說(shuō),數據的一致性非常的高,但系統的可用性卻非常低了。如果R + W > N能夠保證我們“讀我們所寫(xiě)”,Dynamo推薦使用322的組合。
Dynamo系統的數據分區讓整個(gè)網(wǎng)絡(luò )的可擴展性其實(shí)是一個(gè)固定值(你分了多少區,實(shí)際上網(wǎng)絡(luò )里擴展節點(diǎn)的上限就是這個(gè)數),通過(guò)NRW來(lái)達到另外兩個(gè)方 向上的調整。
針對一些經(jīng)??赡艹霈F的問(wèn)題,Dynamo還提供了一些解決的方法。
第一個(gè)是hinted handoff數據的加入:在一個(gè)節點(diǎn)出現臨時(shí)性故障時(shí),數據會(huì )自動(dòng)進(jìn)入列表中的下一個(gè)節點(diǎn)進(jìn)行寫(xiě)操作,并標記為handoff數據,在收到通知需要原節點(diǎn)恢復時(shí)重新把數據推回去。這能使系統的寫(xiě)入成功大大提升。
第二個(gè)是向量時(shí)鐘來(lái)做版本控制:用一個(gè)向量(比如說(shuō)[a,1]表示這個(gè)數據在a節點(diǎn)第一次寫(xiě)入)來(lái)標記數據的版本,這樣在有版本沖突的時(shí)候,可以追溯到出現問(wèn)題的地方。這可以使數據的最終一致成為可能。(Cassandra未用vector clock,而只用client timestamps也達到了同樣效果。)
第三個(gè)是Merkle tree來(lái)提速數據變動(dòng)時(shí)的查找:使用Merkle tree為數據建立索引,只要任意數據有變動(dòng),都將快速反饋出來(lái)。
第四個(gè)是Gossip協(xié)議:一種通訊協(xié)議,目標是讓節點(diǎn)與節點(diǎn)之間通信,省略中心節點(diǎn)的存在,使網(wǎng)絡(luò )達到去中心化。提高系統的可用性。
Dynamo的理論對CAP原則里的可擴展性做到了很方便的實(shí)現,通過(guò)創(chuàng )造性的NRW來(lái)平衡系統的可用性和一致性,增加了系統在實(shí)際情況下遇到問(wèn)題的可選擇方案??梢韵嘞?,在NoSQL的道路上,這只是個(gè)開(kāi)端,在分布式計算的道路上,已經(jīng)是MapReduce之后的再次革命。
聯(lián)系客服