分布式系統(tǒng)架構(gòu)通常需要考慮三個因素:可靠性(Reliability)、可用性(Availability)和一致性(Consistency)。二者不能同時達(dá)到,最多只可以實(shí)現(xiàn)其中的兩個。Dynamo系統(tǒng)選擇犧牲一致性來換取系統(tǒng)的可靠性和可用性,這也是由Amazon業(yè)務(wù)特點(diǎn)決定的。Dynamo要保證完美的用戶體驗(yàn),就必須保證數(shù)據(jù)總是可寫的,但是這樣就可能出現(xiàn)數(shù)據(jù)沖突,如何解決數(shù)據(jù)沖突呢?Dynamo采用了最終一致性模型(Eventual Consistency),這種模型和強(qiáng)一致性模型(Strong Consistency)的不同點(diǎn)在于:它并不在意數(shù)據(jù)更新過程中的一致性問題,只要最終的所有數(shù)據(jù)副本能夠保證一致性即可。簡單地說就是“只求結(jié)果,不看過程”。由于最終一致性模型不保證過程中數(shù)據(jù)的一致性,在某些情況下(比如說某個存儲節(jié)點(diǎn)出現(xiàn)故障)不同的數(shù)據(jù)副本可能會出現(xiàn)不同的版本,如何確保所有的副本最終都會被正確更新是一個很棘手的問題。數(shù)據(jù)副本可能會以不同的順序看到更新結(jié)果,而不同順序的更新很可能造成數(shù)據(jù)的不一致。為此Dynamo利用技術(shù)手段推斷各個更新的實(shí)際發(fā)生次序,這種技術(shù)就是向量時鐘,其原理圖如圖3-6所示。
Dynamo中的向量時鐘用一個(nodes,counter)對表示。其中nodes表示節(jié)點(diǎn), counter是一個計數(shù)器,初始為0,節(jié)點(diǎn)每發(fā)生一次事件就將計數(shù)器加1。首先Sx對某個對象進(jìn)行一次寫操作,產(chǎn)生一個對象版本Dl([Sx,l]),接著Sx再次操作,由于Sx是第二次進(jìn)行操作,所以counter值更新為2,產(chǎn)生第二個版本D2([Sx,2]);之后,Sy和Sz同時對該對象進(jìn)行寫操作,Sy將自身的信息加入向量時鐘產(chǎn)生了新的版本D3([Sx,2], [Sy,l]), Sz同樣產(chǎn)生了新的版本信息D4([Sx,2], [Sz,l]),這時系統(tǒng)中就有了兩個版本的對象,但是系統(tǒng)不會自行選擇,它會將這兩個版本同時保存,等待客戶端解決沖突。最后Sx再次對對象進(jìn)行操作,這時它會同時獲得兩個數(shù)據(jù)版本,用戶根據(jù)版本的信息,重新計算或得一個新的對象記做D5([Sx,2], [S3U],[Sz,l]),并將新的對象保存到系統(tǒng)中。需要注意的是,向量時鐘的數(shù)量是有限制的,當(dāng)超過限制時需根據(jù)時間戳(Timestamp)刪除最開始的一個。這種解決一致性問題的方式對Amazon的購物網(wǎng)站來說非常有用。例如購物車模型,用戶可以通過它查詢曾經(jīng)瀏覽的各種商品,而不是僅僅査詢最終購買的商品。