Dynamo一個缺陷的架構設計(譯)

Dynamo一個缺陷的架構設計(譯)

在雲計算的時代,Dynamo可以說是一本實現分佈式存儲的紅寶書,借鑑Dynamo實現的產品如雨後春筍般冒出。前段時間本人曾在Twitter上戲稱

這年頭,如果一個號稱有“海量數據”的互聯網公司,不做一個自己的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)
汗,有人發現Dynamo是一個缺陷的架構,幸運的是,我們只用它來存儲了成百上億的購物籃數據。:-)

以下是這篇批判Dynamo文章大部分中心觀點,所翻譯的觀點並不代表Tim立場。

–譯文開始–

Dynamo: A flawed architecture

在發表此文章之前,我也爭論過Dynamo是否適合我們的系統。但是我很清楚這篇論文充滿缺陷,它將錯誤的引導了讀者讓大家相信其設計,它的很多設計前後自相矛盾。下文會詳細介紹這些缺陷。

Dynamo的最終一致性

首先,最終一致性對開發者意味什麼呢?

  1. 寫入的數據不能在後續的讀操作中獲取到。
  2. 寫入的數據也有可能在後續的讀操作中獲取到,但讀到後可能下一次又讀不到。
  3. 因此對寫操作後面的讀取沒有SLA(Service Level Agreement)保證。

舉例說明,由於Dynamo是一個key value存儲,我們假設value中存儲的是一個list, 當list寫入數據之後另外一個client卻未讀取到,這時候它需要寫入數據的話只能重新構建一個新的list,添加要存的值並將新list存入,這就會導致老的list數據丟失。

(Update: 論壇上一些人指出,由於Vector Clock機制,數據丟失的場景不可能出現,我同意,不過我再提出幾個其他問題。)

  1. Cassandra未用vector clock, 而只用client timestamps也達到了同樣效果。
  2. Dynamo依賴合併衝突來解決此問題,一些場合下衝突很難解決。比如從list中錯誤的截取操作。(if deletion from the list is a valid operation – then how would one reconcile after mistaken truncation?)
  3. 另外一個場景,讀取到髒數據後可能會影響後續的寫入。(a stale read may end up affecting writes to other keys)

一般的常識是讀取髒數據是需要避免的,但是Dynamo中無任何措施來避免讀取髒數據以及避免讀取髒數據的客戶端再次寫入,這個在單IDC環境其實是完全可以避免的。

Quorum一致性

(譯者注:Quorum是Dynamo的一個核心特性,主要思想是 寫最小節點數W + 讀最小節點數R > 所有節點數N)
Dynamo開始就提到系統按最終一致性設計,但是在4.5中卻提出用Quorum的方法來實現一定程度的一致性,意思是如果R+W>N, 則讀操作就具備(強)一致性了。明顯是誤導。由於節點會出現不可用的情況,尤其在跨IDC情況下,任一節點隨時都有可能離開quorum組,當它離開再加入的時候,R個節點返回的數據就是不一致的,因爲故障節點的數據只具備“最終一致性”,而在當時返回的只能是髒數據。

這就帶來一個明顯的問題,爲什麼要讓未同步到最新數據的節點加入組?答案是Dynamo中無任何方法來判斷一個節點是否數據同步,也無法判斷有哪些數據不同步。因此只能做一個完全數據比較才能判斷,Dynamo中用一種叫Merkle Tree的方法來實現,這個當然是一個代價昂貴且不靈活的操作,因爲爲了不影響Dynamo正常的讀寫業務,同步需要在後臺執行。

實現強一致性也可以用讀取所有節點(R=N)的方式來達到,不過有2個問題。

  1. 一旦有一個節點未同步,讀取就會失敗。
  2. 讀取的代價極高。

我並不是第一個發現這些問題的人,比如另一知名的Cassandra產品Cassandra-225中就提到用一箇中心commit log的方法來解決此問題。

WAN considerations 跨IDC的問題

值得指出的是,如果將Dynamo部署到多個機房,節點的斷續情況會很容易發生。當一個節點連接不到,Dynamo的”hinted handoff”策略會使用一致性哈希算法將數據放入下一個節點。在多IDC環境下,下一節點通常在另一機房,因此會造成異地數據傳輸增加。當異地整個IDC都連不上網絡分裂情況發生時,數據需要很長時間才能完全恢復。

Disaster Recovery 災難恢復

Dynamo最終一致性及同步的設計對於是節點故障是有價值的,但是卻無法估算有多少數據未同步。如果改用常規的commit log方式的話,很容易就能實現故障恢復並且計算未同步的數據量。

未使用時間一致性(譯者:基於timestamp的合併?)在某些場合下很難合併衝突。

一致性還是可用性 Consistency versus Availability

一般認爲Dynamo選擇了CAP理論中的AP,而BigTable選擇了CA。不幸的是,Dynamo並沒有搞清什麼是A(availability)和P(Partition Tolerance)。讀者被誤導只能在C和P中做一個取捨,這個當然是錯的。我們很容易在單IDC實現一致性及高可用性。大部分商業數據庫就是如此,HBase/HDFS也是如此。

很多人誤以爲即使在單IDC架構中,Dynamo方式比BigTable/GFS架構更合理。但Dynamo的優勢其實是在多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.
過去,中心化設計導致了很多災難,我們意識到要遠離中心化。去中心化後,系統會更簡潔,更具有可擴展性及高可用性。

中心化確實會形成瓶頸,但是沒有證據說明中心化就低可用性。大部分專業的存儲系統通過雙機熱備的方式都具備高可用性。簡單的說,只需要所有中心模塊(電源,主板,RAID,交換機等)都按雙份的方式來設計,只需要額外增加一點硬件成本,這些系統基本可以達到5個9的可用性。

值得諷刺的是Dynamo其實在部分情況下還是一箇中心化的體系,如交換機故障發生了網絡分片,服務器分成2個獨立的小網,這時候Dynamo對客戶端是不可用的,儘管客戶端可以連接上Dynamo。

更諷刺的是我們看到Dynamo很多一致性問題都是去中心化設計所導致。

–譯文完–

此文的討論也非常精彩,對於想深入瞭解Dynamo的朋友是不可多得的資料。可參看http://news.ycombinator.com/item?id=915212

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章