在云計(ji)算的(de)時(shi)代,Dynamo可以說是一本實(shi)(shi)現(xian)分(fen)布式(shi)存儲的(de)紅寶書,借鑒(jian)Dynamo實(shi)(shi)現(xian)的(de)產品如雨后春筍般冒出。前段(duan)時(shi)間本人曾在Twitter上戲(xi)稱
這年頭,如果一個號稱有“海量數據”的互聯網公司,不做一個自己的Dynamo,出去都不好意思跟人打招呼
(//twitter.com/xmpp/status/8023241449)
另外一方面對于Dynamo設計思想也有不少反對的聲音,比如2009/11/1在Hacker News上鏈接的一篇文章Dynamo: A flawed architecture引起不少(shao)爭議,最后竟引起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
(//twitter.com/Werner/statuses/5345892061)
汗,有(you)人(ren)發(fa)現Dynamo是(shi)一(yi)個缺陷的架(jia)構,幸運的是(shi),我們只用(yong)它來存儲(chu)了成(cheng)百上億(yi)的購(gou)物籃(lan)數據。:-)
以下是這篇批判(pan)Dynamo文章大部分中(zhong)心觀(guan)點,所翻譯的觀(guan)點并不代表(biao)Tim立場。
–譯文開始–
Dynamo: A flawed architecture
在(zai)發(fa)表此(ci)文章之前(qian)(qian),我也爭論過Dynamo是否適合我們的(de)系統。但是我很(hen)清楚這篇論文充滿(man)缺陷(xian),它將錯誤的(de)引導了讀者(zhe)讓(rang)大家(jia)相信其設(she)計(ji),它的(de)很(hen)多設(she)計(ji)前(qian)(qian)后自相矛盾。下文會(hui)詳(xiang)細介(jie)紹(shao)這些缺陷(xian)。
Dynamo的最終一致性
首先,最終一(yi)致性對開發(fa)者意味什(shen)么呢?
- 寫入的數據不能在后續的讀操作中獲取到。
- 寫入的數據也有可能在后續的讀操作中獲取到,但讀到后可能下一次又讀不到。
- 因此對寫操作后面的讀取沒有SLA(Service Level Agreement)保證。
舉(ju)例(li)說明,由于Dynamo是一(yi)(yi)個(ge)(ge)key value存(cun)儲(chu),我們假(jia)設value中存(cun)儲(chu)的是一(yi)(yi)個(ge)(ge)list, 當list寫入(ru)數據(ju)之后另外一(yi)(yi)個(ge)(ge)client卻未讀取(qu)到,這時候它需(xu)要(yao)寫入(ru)數據(ju)的話只(zhi)能重新(xin)構建一(yi)(yi)個(ge)(ge)新(xin)的list,添加要(yao)存(cun)的值并將(jiang)新(xin)list存(cun)入(ru),這就會導致老的list數據(ju)丟失(shi)。
(Update: 論壇上一些(xie)人指出(chu),由于Vector Clock機(ji)制(zhi),數據丟失的場景不可(ke)能出(chu)現(xian),我同意,不過我再提出(chu)幾個其他問題。)
- Cassandra未用vector clock, 而只用client timestamps也達到了同樣效果。
- Dynamo依賴合并沖突來解決此問題,一些場合下沖突很難解決。比如從list中錯誤的截取操作。(if deletion from the list is a valid operation – then how would one reconcile after mistaken truncation?)
- 另外一個場景,讀取到臟數據后可能會影響后續的寫入。(a stale read may end up affecting writes to other keys)
一般(ban)的(de)常識(shi)是(shi)讀取(qu)臟(zang)數據是(shi)需要避(bi)(bi)(bi)免的(de),但是(shi)Dynamo中無任何措施來避(bi)(bi)(bi)免讀取(qu)臟(zang)數據以及避(bi)(bi)(bi)免讀取(qu)臟(zang)數據的(de)客(ke)戶端(duan)再次寫入,這個(ge)在單IDC環境(jing)其(qi)實是(shi)完全可(ke)以避(bi)(bi)(bi)免的(de)。
Quorum一致性
(譯者注:Quorum是Dynamo的一個核心特性,主要思想是 寫最小節點數W + 讀最小節點數R > 所有節點數N)
Dynamo 開(kai)始(shi)就(jiu)提到(dao)系統按最終(zhong)一(yi)(yi)致(zhi)性(xing)(xing)(xing)設計,但(dan)是(shi)在4.5中卻提出用(yong)Quorum的(de)(de)方(fang)法(fa)來實現一(yi)(yi)定程度的(de)(de)一(yi)(yi)致(zhi)性(xing)(xing)(xing),意思(si)是(shi)如果R+W>N, 則讀(du)操作就(jiu)具備(強)一(yi)(yi)致(zhi)性(xing)(xing)(xing)了(le)。明顯是(shi)誤導。由(you)于節點會出現不可用(yong)的(de)(de)情況,尤其在跨IDC情況下,任一(yi)(yi)節點隨(sui)時(shi)都有(you)可能(neng)離開(kai)quorum組,當它離開(kai)再加(jia)入(ru)的(de)(de)時(shi)候,R個節點返回的(de)(de)數據就(jiu)是(shi)不一(yi)(yi)致(zhi)的(de)(de),因為(wei)故障(zhang)節點的(de)(de)數據只具備“最終(zhong)一(yi)(yi)致(zhi)性(xing)(xing)(xing)”,而(er)在當時(shi)返回的(de)(de)只能(neng)是(shi)臟數據。
這就(jiu)帶來一個(ge)明(ming)顯的問題(ti),為什么要(yao)讓未(wei)同(tong)(tong)步(bu)到最(zui)新數據(ju)(ju)的節點加入(ru)組?答案是(shi)Dynamo中(zhong)無任何方法(fa)來判(pan)斷(duan)一個(ge)節點是(shi)否(fou)數據(ju)(ju)同(tong)(tong)步(bu),也無法(fa)判(pan)斷(duan)有哪些數據(ju)(ju)不同(tong)(tong)步(bu)。因(yin)此只能做一個(ge)完全數據(ju)(ju)比較才(cai)能判(pan)斷(duan),Dynamo中(zhong)用一種(zhong)叫Merkle Tree的方法(fa)來實現,這個(ge)當然是(shi)一個(ge)代價昂(ang)貴且不靈(ling)活的操作,因(yin)為為了不影響Dynamo正常的讀寫業務,同(tong)(tong)步(bu)需要(yao)在后(hou)臺執行。
實現強一致性也可以用(yong)讀(du)取所有(you)節點(R=N)的方式來(lai)達到(dao),不過(guo)有(you)2個問題。
- 一旦有一個節點未同步,讀取就會失敗。
- 讀取的代價極高。
我并不是第一個發現這些問題的(de)人,比如(ru)另一知名的(de)Cassandra產(chan)品
WAN considerations 跨IDC的問題
值得指出(chu)的(de)是,如果(guo)將(jiang)Dynamo部署到(dao)多個機(ji)房,節(jie)點(dian)的(de)斷續情況(kuang)會很容易發(fa)生。當一(yi)個節(jie)點(dian)連接(jie)不到(dao),Dynamo的(de)”hinted handoff”策略會使用一(yi)致性哈希算法將(jiang)數據放入下一(yi)個節(jie)點(dian)。在多IDC環境(jing)下,下一(yi)節(jie)點(dian)通常在另(ling)一(yi)機(ji)房,因此會造成異地(di)數據傳輸增加。當異地(di)整個 IDC都連不上網(wang)絡分裂情況(kuang)發(fa)生時(shi),數據需要(yao)很長(chang)時(shi)間才能完全恢復。
Disaster Recovery 災難恢復
Dynamo最(zui)終(zhong)一致性及(ji)同步的(de)設計(ji)對于是節點故障是有價值的(de),但是卻(que)無法估算有多少數據未(wei)同步。如果改用常規的(de)commit log方式(shi)的(de)話,很(hen)容易就能實現(xian)故障恢復并且計(ji)算未(wei)同步的(de)數據量。
未使用時間一致性(譯者:基于(yu)timestamp的(de)合并?)在某些場合下很難合并沖突。
一致性還是可用性 Consistency versus Availability
一(yi)(yi)般認為(wei)Dynamo選擇了CAP理論中的AP,而(er)BigTable選擇了CA。不幸的是(shi),Dynamo并(bing)沒有搞清什么(me)是(shi) A(availability)和P(Partition Tolerance)。讀者被誤導只能在C和P中做(zuo)一(yi)(yi)個取舍,這(zhe)個當然是(shi)錯的。我們(men)很容(rong)易(yi)在單IDC實現(xian)一(yi)(yi)致性及高可(ke)用(yong)性。大部分商(shang)業(ye)數據庫就是(shi)如此,HBase/HDFS也是(shi)如此。
很多人誤(wu)以為即使在(zai)單IDC架(jia)構(gou)中,Dynamo方式比BigTable/GFS架(jia)構(gou)更(geng)合理(li)。但Dynamo的優勢其實是在(zai)多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.
過去,中心化設(she)計導致了很(hen)多災難,我們(men)意識到要遠離(li)中心化。去中心化后(hou),系統會更簡潔,更具有可(ke)擴展(zhan)性(xing)及高可(ke)用性(xing)。
中心化(hua)確實會形成(cheng)瓶頸,但(dan)是沒有(you)證據說明(ming)中心化(hua)就低可(ke)(ke)用(yong)(yong)性。大部分專業的(de)存(cun)儲系(xi)統通過雙機(ji)熱備的(de)方式都(dou)具備高(gao)可(ke)(ke)用(yong)(yong)性。簡單的(de)說,只需要(yao)(yao)所有(you)中心模塊(電源,主板,RAID,交換機(ji)等)都(dou)按雙份的(de)方式來設計,只需要(yao)(yao)額(e)外增加一點硬件成(cheng)本(ben),這(zhe)些系(xi)統基(ji)本(ben)可(ke)(ke)以(yi)達到(dao)5個9的(de)可(ke)(ke)用(yong)(yong)性。
值得諷刺(ci)的是Dynamo其(qi)實在(zai)部分(fen)情況下還是一個中(zhong)心化的體系,如交換機(ji)故障發生了網(wang)絡分(fen)片,服務(wu)器分(fen)成(cheng)2個獨立的小網(wang),這時候(hou)Dynamo對客戶端是不可用的,盡管客戶端可以連接上(shang)Dynamo。
更諷刺的是我們看到(dao)Dynamo很多一(yi)致性問題都(dou)是去中心化設計所導致。
–譯文完–
此文(wen)的討論也非常精彩,對于想(xiang)深(shen)入了(le)解(jie)Dynamo的朋友是(shi)不可(ke)多(duo)得的資料(liao)。
