在云計算的時代,Dynamo可以說是一本實現(xiàn)分布式存儲的紅寶書,借鑒Dynamo實現(xiàn)的產(chǎn)品如雨后春筍般冒出。前段時間本人曾在Twitter上戲稱
這年頭,如果一個號稱有“海量數(shù)據(jù)”的互聯(lián)網(wǎng)公司,不做一個自己的Dynamo,出去都不好意思跟人打招呼
(http://twitter.com/xmpp/status/8023241449)
另外一方面對于Dynamo設計思想也有不少反對的聲音,比如2009/11/1在Hacker News上鏈接的一篇文章Dynamo: A flawed architecture引起不少爭議,最后竟引起Amazon CTO Werner Vogels在Twitter上回應
Darn, someone figured out that Dynamo is a flawed architecture. Luckily its only use is storing hundreds of millions of shopping carts
(http://twitter.com/Werner/statuses/5345892061)
汗,有人發(fā)現(xiàn)Dynamo是一個缺陷的架構,幸運的是,我們只用它來存儲了成百上億的購物籃數(shù)據(jù)。:-)
以下是這篇批判Dynamo文章大部分中心觀點,所翻譯的觀點并不代表Tim立場。
–譯文開始–
Dynamo: A flawed architecture
在發(fā)表此文章之前,我也爭論過Dynamo是否適合我們的系統(tǒng)。但是我很清楚這篇論文充滿缺陷,它將錯誤的引導了讀者讓大家相信其設計,它的很多設計前后自相矛盾。下文會詳細介紹這些缺陷。
Dynamo的最終一致性
首先,最終一致性對開發(fā)者意味什么呢?
- 寫入的數(shù)據(jù)不能在后續(xù)的讀操作中獲取到。
- 寫入的數(shù)據(jù)也有可能在后續(xù)的讀操作中獲取到,但讀到后可能下一次又讀不到。
- 因此對寫操作后面的讀取沒有SLA(Service Level Agreement)保證。
舉例說明,由于Dynamo是一個key value存儲,我們假設value中存儲的是一個list, 當list寫入數(shù)據(jù)之后另外一個client卻未讀取到,這時候它需要寫入數(shù)據(jù)的話只能重新構建一個新的list,添加要存的值并將新list存入,這就會導致老的list數(shù)據(jù)丟失。
(Update: 論壇上一些人指出,由于Vector Clock機制,數(shù)據(jù)丟失的場景不可能出現(xiàn),我同意,不過我再提出幾個其他問題。)
- Cassandra未用vector clock, 而只用client timestamps也達到了同樣效果。
- Dynamo依賴合并沖突來解決此問題,一些場合下沖突很難解決。比如從list中錯誤的截取操作。(if deletion from the list is a valid operation – then how would one reconcile after mistaken truncation?)
- 另外一個場景,讀取到臟數(shù)據(jù)后可能會影響后續(xù)的寫入。(a stale read may end up affecting writes to other keys)
一般的常識是讀取臟數(shù)據(jù)是需要避免的,但是Dynamo中無任何措施來避免讀取臟數(shù)據(jù)以及避免讀取臟數(shù)據(jù)的客戶端再次寫入,這個在單IDC環(huán)境其實是完全可以避免的。
Quorum一致性
(譯者注:Quorum是Dynamo的一個核心特性,主要思想是 寫最小節(jié)點數(shù)W + 讀最小節(jié)點數(shù)R > 所有節(jié)點數(shù)N)
Dynamo 開始就提到系統(tǒng)按最終一致性設計,但是在4.5中卻提出用Quorum的方法來實現(xiàn)一定程度的一致性,意思是如果R+W>N, 則讀操作就具備(強)一致性了。明顯是誤導。由于節(jié)點會出現(xiàn)不可用的情況,尤其在跨IDC情況下,任一節(jié)點隨時都有可能離開quorum組,當它離開再加入的時候,R個節(jié)點返回的數(shù)據(jù)就是不一致的,因為故障節(jié)點的數(shù)據(jù)只具備“最終一致性”,而在當時返回的只能是臟數(shù)據(jù)。
這就帶來一個明顯的問題,為什么要讓未同步到最新數(shù)據(jù)的節(jié)點加入組?答案是Dynamo中無任何方法來判斷一個節(jié)點是否數(shù)據(jù)同步,也無法判斷有哪些數(shù)據(jù)不同步。因此只能做一個完全數(shù)據(jù)比較才能判斷,Dynamo中用一種叫Merkle Tree的方法來實現(xiàn),這個當然是一個代價昂貴且不靈活的操作,因為為了不影響Dynamo正常的讀寫業(yè)務,同步需要在后臺執(zhí)行。
實現(xiàn)強一致性也可以用讀取所有節(jié)點(R=N)的方式來達到,不過有2個問題。
- 一旦有一個節(jié)點未同步,讀取就會失敗。
- 讀取的代價極高。
我并不是第一個發(fā)現(xiàn)這些問題的人,比如另一知名的Cassandra產(chǎn)品Cassandra-225中就提到用一個中心commit log的方法來解決此問題。
WAN considerations 跨IDC的問題
值得指出的是,如果將Dynamo部署到多個機房,節(jié)點的斷續(xù)情況會很容易發(fā)生。當一個節(jié)點連接不到,Dynamo的”hinted handoff”策略會使用一致性哈希算法將數(shù)據(jù)放入下一個節(jié)點。在多IDC環(huán)境下,下一節(jié)點通常在另一機房,因此會造成異地數(shù)據(jù)傳輸增加。當異地整個 IDC都連不上網(wǎng)絡分裂情況發(fā)生時,數(shù)據(jù)需要很長時間才能完全恢復。
Disaster Recovery 災難恢復
Dynamo最終一致性及同步的設計對于是節(jié)點故障是有價值的,但是卻無法估算有多少數(shù)據(jù)未同步。如果改用常規(guī)的commit log方式的話,很容易就能實現(xiàn)故障恢復并且計算未同步的數(shù)據(jù)量。
未使用時間一致性(譯者:基于timestamp的合并?)在某些場合下很難合并沖突。
一致性還是可用性 Consistency versus Availability
一般認為Dynamo選擇了CAP理論中的AP,而BigTable選擇了CA。不幸的是,Dynamo并沒有搞清什么是 A(availability)和P(Partition Tolerance)。讀者被誤導只能在C和P中做一個取舍,這個當然是錯的。我們很容易在單IDC實現(xiàn)一致性及高可用性。大部分商業(yè)數(shù)據(jù)庫就是如此,HBase/HDFS也是如此。
很多人誤以為即使在單IDC架構中,Dynamo方式比BigTable/GFS架構更合理。但Dynamo的優(yōu)勢其實是在多IDC。
中心化還是去中心化
Dynamo中提到
In the past, centralized control has resulted in outages and the goal is to avoid it as much as possible. This leads to a simpler, more scalable, and more available system.
過去,中心化設計導致了很多災難,我們意識到要遠離中心化。去中心化后,系統(tǒng)會更簡潔,更具有可擴展性及高可用性。
中心化確實會形成瓶頸,但是沒有證據(jù)說明中心化就低可用性。大部分專業(yè)的存儲系統(tǒng)通過雙機熱備的方式都具備高可用性。簡單的說,只需要所有中心模塊(電源,主板,RAID,交換機等)都按雙份的方式來設計,只需要額外增加一點硬件成本,這些系統(tǒng)基本可以達到5個9的可用性。
值得諷刺的是Dynamo其實在部分情況下還是一個中心化的體系,如交換機故障發(fā)生了網(wǎng)絡分片,服務器分成2個獨立的小網(wǎng),這時候Dynamo對客戶端是不可用的,盡管客戶端可以連接上Dynamo。
更諷刺的是我們看到Dynamo很多一致性問題都是去中心化設計所導致。
–譯文完–
此文的討論也非常精彩,對于想深入了解Dynamo的朋友是不可多得的資料。
![[譯稿]Dynamo一個缺陷的架構設計,互聯(lián)網(wǎng)的一些事](/uploads/allimg/100309/23142B543-0.gif)
