再談最終一致

在世界範圍構建可靠的分佈式系統往往要求在一致性和可用性之間進行權衡。上個月,亞馬遜公司的CTO Werner Vogels發表了一篇文章,描述在大型分佈式系統中容忍最終數據一致性的方法。 正如InfoQ之前的一篇新聞裏所討論的: 系統架構師角色關鍵的一方面就是衡量相互衝突的需求、決定解決方案,常常要犧牲一個方面來換取另一個方面。 亞馬遜公司的CTO Werner Vogels發佈的新帖子討論了這些基本需求如何應用於基礎設施服務,爲構建Internet範圍的計算平臺提供資源。 鑑於這些系統分佈在世界範圍內,我們處處利用複製技術來保證穩定的性能和高可用性。儘管複製技術使我們達到部分目的,但它的實現並不是完全透明的;在許多情況下,在服務內部使用複製技術都會給服務的客戶帶來後果。後果之一體現爲對數據一致性的限制,特別是在底層分佈式系統提供了一種最終一致的數據複製模型的時候。在亞馬遜設計這些大型系統時,我們憑藉一套有關大規模數據複製的指導原則和抽象,把注意力集中於高可用性和數據一致性之間的權衡選擇。 按照Werner所說,考慮一致性有兩種方式:一種是從開發者/客戶端的角度——他們如何觀察數據更新。第二種是從服務器的角度——更新如何流經整個系統,系統對更新有何保證。 在定義客戶端一致性模型時應該考慮的內容如下: 存儲系統……它在本質上是大規模且高度分佈的系統,其創建目的是爲了保證耐用性和可用性。 進程A。對存儲系統進行讀寫。 進程B和C。這兩個進程完全獨立於進程A,也讀寫存儲系統……客戶端一致性必須處理一個觀察者(在此即進程A、B或C)如何以及何時看到存儲系統中的一個數據對象被更新。 強一致性。在更新完成後,(A、B或C進行的)任何後續訪問都將返回更新過的值。 弱一致性。系統不保證後續訪問將返回更新過的值,在那之前要先滿足若干條件。從更新到保證任一觀察者看到更新值的時刻之間的這段時間被稱爲不一致窗口。 最終一致性。這是弱一致性的一種特殊形式;存儲系統保證如果對象沒有新的更新,最終所有訪問都將返回最後更新的值。如果沒有發生故障,不一致窗口的最大值可以根據下列因素確定:比如通信延遲、系統負載、複製方案涉及的副本數量。 客戶端一致性模型的變體有: 因果一致性。如果進程A通知進程B它已更新了一個數據項,那麼進程B的後續訪問將返回更新後的值,且一次寫入將保證取代前一次寫入。與進程A無因果關係的進程C的訪問遵守一般的最終一致性規則。 “讀己之所寫”一致性。這是一個重要的模型。當進程A自己更新一個數據項之後,它總是訪問到更新過的值,絕不會看到舊值。這是因果一致性模型的一個特例。 會話一致性。這是上一個模型的實用版本,它把訪問存儲系統的進程放到會話的上下文中。只要會話還存在,系統就保證“讀己之所寫”一致性……系統的保證也不會延續到新的會話。 單調讀一致性。如果進程已經看到過數據對象的某個值,那麼任何後續訪問都不會返回在那個值之前的值。 單調寫一致性。系統保證來自同一個進程的寫操作順序執行。要是系統不能保證這種程度的一致性,就非常難以編程了。 服務器端的一致性水平取決於如何在數據副本之間傳播更新(這是改善吞吐量、提供可伸縮性的典型方式)。只有部分數據副本參與更新操作,且/或作爲讀操作的一部分與其它副本進行聯繫時,就會出現弱/最終一致性。發生這種情況的兩種常見場景分別是爲讀伸縮而做大量複製的情況和有複雜數據訪問的情況。在大多數這樣的系統中,更新以一種“懶”方式傳播到副本集內的其它節點上。所有副本都完成更新前的這段時間就是不一致窗口,讀取尚未接收到更新的節點是整個系統的薄弱環節。服務器提供的一致性水平可以通過客戶端/服務器通信的特定實現來改進,或者由客戶端自己來完成: “讀己之所寫”一致性、會話一致性和單調一致性是否可以達成,取決於客戶端對爲其執行分佈式協議的服務器的“粘度”。如果每次都是同一臺服務器,那麼就比較容易保證“讀己之所寫”一致性和單調一致性。這樣做會使管理負載平衡以及容錯變得稍困難一些,但這是一種簡單的方案…… 客戶端有時會實現“讀己之所寫”一致性和單調讀一致性。通過給寫入添加版本,對那些版本早於最後版本的值來說,客戶端會丟棄這些值的讀出。 每個客戶端應用對服務器造成的不一致性都有自己的耐受力,但在任何情況下,客戶端應用都應該知道服務器應用提供的一致性水平。有很多改善最終一致性模型的實用方法,比如會話級別的一致性和單調讀一致性,它們都爲開發人員提供了更好的工具。 查看英文原文:Eventually Consistent, Revisited
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章