首頁>技術>

大約一年前,我在一致性模型上寫了這篇文章的第一個版本,但我從來沒有對它感到滿意,因為它寫得很匆忙,而且這個主題足夠重要,需要得到更徹底的處理。ACM Queue要求我修改它以便在他們的雜誌中使用,我利用這個機會改進了這篇文章。這是那個新版本。

最終的一致性——在全球範圍內構建可靠的分散式系統需要在一致性和可用性之間進行權衡。

亞馬遜雲計算的基礎是基礎設施服務,如Amazon的S3(簡單儲存服務)、SimpleDB和EC2(彈性計算雲),它們為構建網際網路規模的計算平臺和各種應用程式提供了資源。對這些基礎設施服務的要求非常嚴格;他們需要在安全性、可伸縮性、可用性、效能和成本效益方面取得高分,並且他們需要在滿足這些需求的同時,持續地為全球各地的數百萬客戶服務。

在這些服務的背後是在全球範圍內執行的大規模分散式系統。這種規模帶來了額外的挑戰,因為當系統處理數萬億、數萬億的請求時,通常發生機率很低的事件現在保證會發生,需要在系統的設計和體系結構中預先考慮。考慮到這些系統的全球範圍,我們廣泛地使用複製技術來保證一致的效能和高可用性。儘管複製使我們更接近我們的目標,但它不能以完全透明的方式實現它們;在許多情況下,這些服務的客戶將面臨在服務內部使用複製技術的後果。

其表現方式之一是所提供的資料一致性型別,特別是當底層分散式系統為資料複製提供最終一致性模型時。在Amazon設計這些大規模系統時,我們使用一組與大規模資料複製相關的指導原則和抽象,並關注高可用性和資料一致性之間的權衡。在本文中,我將介紹一些相關的背景知識,這些背景知識為我們提供了交付需要在全球範圍內執行的可靠分散式系統的方法。這篇文章的早期版本出現在2007年12月的All Things Distributed weblog上,並在讀者的幫助下得到了極大的改進。

歷史的角度

在理想的世界中,只有一個一致性模型:當進行更新時,所有觀察者都將看到該更新。第一次出現這種難以實現的情況是在70年代末的資料庫系統中。關於這個主題最好的“時期文章”是Bruce Lindsay等人寫的“分散式資料庫的註釋”5。它列出了資料庫複製的基本原則,並討論了實現一致性的許多技術。這些技術中的許多都試圖實現分佈透明性—也就是說,對於系統的使用者來說,看起來好像只有一個系統,而不是有許多協作系統。這一時期的許多系統採取的方法是,與其破壞這種透明度,不如讓整個系統失靈

在90年代中期,隨著大型網際網路系統的興起,這些做法被重新審視。那時,人們開始考慮可用性可能是這些系統最重要的屬性,但他們也在為它應該與什麼進行交換而掙扎。系統教授Eric Brewer的加州大學伯克利分校,當時Inktomi,帶來了不同的交換在主題演講PODC 2000.1(分散式計算的原則)會議上他提出上限定理,即三個屬性的資料共享系統資料一致性、系統可用性和公差網路partition-only兩個可以實現在任何給定的時間。Seth Gilbert和Nancy lynch在2002年的一篇論文中給出了更正式的確認

不能容忍網路分割槽的系統可以實現資料一致性和可用性,通常是透過使用事務協議實現的。要做到這一點,客戶端和儲存系統必須是同一個環境的一部分;在某些場景下,它們作為一個整體失敗,因此,客戶端無法觀察分割槽。一個重要的觀察結果是,在較大的分散式系統中,網路分割槽是給定的;因此,一致性和可用性不能同時實現。這意味著對於放棄什麼有兩種選擇:放鬆一致性將允許系統在可分割槽條件下保持高可用性,而將一致性作為優先順序意味著在某些條件下系統將不可用。

這兩個選項都要求客戶端開發人員知道系統提供了什麼。如果系統強調一致性,開發人員就必須處理這樣一個事實,即系統可能無法進行寫入操作。如果由於系統不可用而導致寫入失敗,那麼開發人員將不得不處理如何處理要寫入的資料。如果系統強調可用性,它可能總是接受寫操作,但在某些條件下,讀操作不會反映最近完成的寫操作的結果。然後開發人員必須決定客戶端是否一直需要訪問絕對最新的更新。有一系列應用程式可以處理稍微陳舊的資料,它們在此模型下得到了很好的服務。

原則上,ACID屬性(原子性、一致性、隔離性、永續性)中定義的事務系統的一致性屬性是一種不同型別的一致性保證。在ACID中,一致性指的是保證事務完成時資料庫處於一致狀態;例如,當從一個賬戶向另一個賬戶轉賬時,兩個賬戶中的總金額不應改變。在基於acid的系統中,這種一致性通常是編寫事務的開發人員的責任,但是資料庫管理完整性約束可以幫助實現這種一致性。

一致性:客戶端和伺服器

有兩種觀察一致性的方法。一個是從開發人員/客戶的角度:他們如何觀察資料更新。第二種方法來自伺服器端:更新如何流經系統,以及系統對更新可以提供哪些保證。

客戶端一致性

客戶端有以下元件:

一個儲存系統。目前,我們將把它看作一個黑盒,但是我們應該假設它是一個大規模的、高度分散式的東西,並且構建它是為了保證永續性和可用性。程序a。這是一個讀寫儲存系統的程序。程序B和程序c是獨立於程序A的兩個程序,它們對儲存系統進行讀寫。它們是同一個程序中的程序還是執行緒無關緊要;重要的是,他們是獨立的,需要交流來共享資訊。客戶端一致性與觀察者(在本例中是程序A、B或C)如何以及何時看到儲存系統中資料物件的更新有關。在下面演示不同型別一致性的例子中,程序A對資料物件進行了更新:強烈的一致性。更新完成後,任何後續訪問(A、B或C)都將返回更新後的值。弱一致性。系統不保證後續訪問將返回更新後的值。在返回值之前,需要滿足許多條件。從更新到保證任何觀察者都能看到更新值這段時間被稱為不一致視窗。最終一致性。這是弱一致性的一種特殊形式;儲存系統保證,如果沒有對物件進行新的更新,最終所有訪問都將返回最後更新的值。如果沒有發生故障,可以根據通訊延遲、系統負載和複製方案中涉及的副本數量等因素確定不一致視窗的最大大小。實現最終一致性的最普遍的系統是DNS(域名系統)。對名稱的更新根據配置的模式進行分發,並與時間控制的快取相結合;最終,所有客戶端都將看到更新。

最終一致性模型有許多重要的變化需要考慮:

因果一致性。如果程序A通知程序B它已經更新了一個數據項,那麼程序B的後續訪問將返回更新後的值,並且保證一次寫操作將取代之前的寫操作。程序C的訪問與程序A沒有因果關係,遵循通常的最終一致性規則。“讀己之所寫”一致性。這是一個重要的模型,流程A在更新了資料項之後,總是訪問更新後的值,永遠不會看到舊的值。這是因果一致性模型的一個特例。會話一致性。這是前一個模型的實際版本,其中程序在會話上下文中訪問儲存系統。只要會話存在,系統就保證“讀己之所寫”一致性。如果會話因為某種失敗場景而終止,則需要建立一個新的會話,並且保證會話不會重疊。單調讀一致性。如果程序已經看到了該物件的特定值,那麼任何後續訪問都不會返回任何以前的值。單調寫一致性。在這種情況下,系統保證序列化同一個程序的寫操作。不能保證這種級別一致性的系統是出了名的難以程式設計。

這些屬性中有許多是可以組合的。例如,可以結合會話級別一致性獲得單調的讀取。從實際的角度來看,這兩個屬性(單調讀取和read-your-write)在最終的一致性系統中是最理想的,但並不總是必需的。這兩個屬性使開發人員更容易構建應用程式,同時允許儲存系統放鬆一致性並提供高可用性。

正如您可以從這些變化中看到的,相當多的不同場景是可能的。能否處理這些後果取決於特定的應用程式。

最終一致性並不是極端分散式系統的神秘屬性。許多提供主備份可靠性的現代rdbms(關係資料庫管理系統)同時以同步和非同步模式實現它們的複製技術。在同步模式下,副本更新是事務的一部分。在非同步模式下,更新以延遲的方式到達備份,通常透過日誌傳送。在後一種模式中,如果主備份在傳送日誌之前發生故障,從提升後的備份讀取資料將產生舊的、不一致的值。另外,為了支援更好的可伸縮讀效能,rdbms已經開始提供從備份中讀取資料的能力,這是提供最終一致性保證的經典案例,在這種情況下,不一致性視窗取決於日誌傳送的週期。

伺服器端一致性

在伺服器端,我們需要更深入地研究更新如何流經系統,以理解是什麼驅動了使用系統的開發人員可以體驗不同的模式。在開始之前,讓我們先建立一些定義:

N =儲存資料副本的節點數

W =在更新完成之前需要確認已收到更新的副本的數量

R =透過讀操作訪問資料物件時所接觸的副本數

如果W+R > N,那麼寫集和讀集總是重疊的,可以保證強一致性。在實現同步複製的主備份RDBMS場景中,N=2、W=2和R=1。無論客戶端從哪個副本讀取資料,它都將得到一致的答案。在啟用了從備份讀取資料的非同步複製中,N=2, W=1, R=1。在這種情況下,R+W=N,一致性無法保證。

這些配置是基本的quorum協議,它們的問題在於,當系統由於故障而無法寫入W個節點時,寫入操作必須失敗,標誌著系統不可用。當N=3 W=3且只有兩個節點可用時,系統將不得不失敗寫操作。

在需要提供高效能和高可用性的分散式儲存系統中,副本的數量通常大於兩個。只關注容錯的系統通常使用N=3 (W=2和R=2配置)。需要提供非常高讀負載的系統經常複製超出容錯要求的資料;N可以是數十個甚至數百個節點,R配置為1,這樣一次讀取就會返回一個結果。關注一致性的系統被設定為W=N進行更新,這可能會降低寫入成功的可能性。這些系統關注容錯性但不具有一致性,它們的一種常見配置是使用W=1執行以獲得最小的更新永續性,然後依賴一種惰性(流行)技術來更新其他副本。

如何配置N、W和R取決於常見情況是什麼,以及需要最佳化哪些效能路徑。在R=1和N=W的情況下,我們最佳化讀的情況,而在W=1和R=N的情況下,我們最佳化寫的非常快。當然,在後一種情況下,在存在故障的情況下,永續性不能得到保證,如果W < (N+1)/2,那麼當寫集不重疊時,就有可能出現寫衝突。

當W+R <= N時出現弱/最終一致性,這意味著讀寫集有可能不重疊。如果這是一個有意的配置,並且不是基於失敗的情況,那麼將R設為1以外的任何值都沒有意義。這種情況通常發生在兩種情況中:第一種是前面提到的為了讀擴充套件而進行的大規模複製;第二個問題是資料訪問更加複雜。在簡單的鍵-值模型中,比較不同版本以確定寫入系統的最新值很容易,但是在返回物件集的系統中,確定正確的最新值集就比較困難了。在大多數寫集小於副本集的系統中,會有一種機制以一種惰性的方式將更新應用到副本集的其餘節點。直到所有副本都被更新為止的時間段是前面討論過的不一致視窗。如果W+R <= N,則系統容易從尚未接收到更新的節點讀取資料。

“讀你的寫”、會話和單調一致性是否可以實現,通常取決於客戶機對執行它們的分散式協議的伺服器的“粘性”。如果每次都是相同的伺服器,則相對容易保證“讀己之所寫”和單調的讀取。這使得管理負載平衡和容錯稍微困難一些,但這是一個簡單的解決方案。使用會話,這是粘性的,使這一點顯式,並提供了一個客戶端可以推理的公開級別。

有時客戶端實現read-your-write和單調讀取。透過在寫操作上新增版本,客戶端將丟棄對版本在最後一個版本之前的值的讀取。

當系統中的一些節點無法到達其他節點時,就會發生分割槽,但兩個節點集都可以被客戶端組訪問。如果您使用傳統的多數仲裁方法,那麼具有W個副本集節點的分割槽可以繼續進行更新,而另一個分割槽變得不可用。對於讀集也是如此。給定這兩個集重疊,根據定義,少數集變得不可用。分割槽並不經常發生,但確實會發生在資料中心之間以及資料中心內部。

在某些應用程式中,任何分割槽的不可用性都是不可接受的,重要的是能夠到達該分割槽的客戶機能夠取得進展。在這種情況下,雙方分配一組新的儲存節點來接收資料,並在分割槽癒合時執行合併操作。例如,在Amazon中購物車使用這樣的write-always系統;在分割槽的情況下,客戶可以繼續將商品放入購物車,即使原來的購物車存在於其他分割槽上。一旦分割槽恢復,cart應用程式將幫助儲存系統合併購物車。

亞馬遜的Dynamo

Amazon的Dynamo系統將所有這些屬性置於應用程式體系結構的顯式控制之下,這是一個鍵值儲存系統,在組成Amazon電子商務平臺的許多服務以及Amazon的Web服務內部使用該系統。Dynamo的設計目標之一是允許建立Dynamo儲存系統例項(通常跨越多個數據中心)的應用程式服務所有者在一致性、永續性、可用性和效能之間以一定的成本進行權衡

總結

在大規模可靠分散式系統中,必須容忍資料不一致性,原因有二:提高高併發條件下的讀寫效能;以及處理大多數模型會導致部分系統不可用的分割槽情況,即使節點已經啟動並執行。

不一致是否可以接受取決於客戶機應用程式。在所有情況下,開發人員都需要意識到,儲存系統提供了一致性保證,並且在開發應用程式時需要考慮到這一點。對於最終一致性模型有許多實際的改進,比如會話級一致性和單調讀取,它們為開發人員提供了更好的工具。很多時候,應用程式都能夠毫無問題地處理儲存系統的最終一致性保證。一個特定的流行案例是一個網站,在其中我們可以有使用者感知一致性的概念。在此場景中,不一致性視窗需要小於客戶返回下一頁載入的預期時間。這允許更新在預期下一次讀取之前在系統中傳播。

本文的目標是提高對工程系統複雜性的認識,這些系統需要在全球範圍內執行,並且需要仔細調優,以確保它們能夠交付應用程式所需的永續性、可用性和效能。系統設計者擁有的工具之一是一致性視窗的長度,在此期間,系統的客戶可能暴露在大規模系統工程的現實中。

本文:http://jiagoushi.pro/node/1387

16
  • BSA-TRITC(10mg/ml) TRITC-BSA 牛血清白蛋白改性標記羅丹明
  • 要想學好MQ!就看這份阿里大牛編寫的深入RabbitMQ指南