分散式系統的一致性探討

HollisChuang發表於2015-12-05

隨著大型網站的各種高併發訪問、海量資料處理等場景越來越多,如何實現網站的高可用、易伸縮、可擴充套件、安全等目標就顯得越來越重要。為了解決這樣一系列問題,大型網站的架構也在不斷髮展。提高大型網站的高可用架構,不得不提的就是分散式。在《初識分散式系統》一文中簡單介紹了分散式的基本概念,本文將在上篇文章的基礎上繼續學習分散式的一致性問題。主要介紹分散式一致性的基本概念、重要性、一致性模型等。

一致性的重要性

分散式領域CAP理論告訴我們,任何一個分散式系統都無法同時滿足Consistency(一致性)、Availability(可用性)、Partition tolerance(分割槽容錯性) 這三個基本需求。最多隻能滿足其中兩項。 但是,一個分散式系統無論在CAP三者之間如何權衡,都無法徹底放棄一致性(Consistency),如果真的放棄一致性,那麼就說明這個系統中的資料根本不可信,資料也就沒有意義,那麼這個系統也就沒有任何價值可言。所以,無論如何,分散式系統的一致性問題都需要重點關注。(分散式系統的CAP理論分散式系統的BASE理論)

這裡先簡單提一下,由於一個分散式系統不可能放棄一致性,那麼為什麼有的架構師還說在某些場景中可以犧牲一致性呢?通常這裡說的放棄一致性指的是放棄資料的強一致性(後文介紹什麼是強一致性)。

通常情況下,我們所說的分散式一致性問題通常指的是資料一致性問題。那麼我們就先來了解一下什麼是資料一致性。

資料一致性

資料一致性其實是資料庫系統中的概念。我們可以簡單的把一致性理解為正確性或者完整性,那麼資料一致性通常指關聯資料之間的邏輯關係是否正確和完整。我們知道,在資料庫系統中通常用事務(訪問並可能更新資料庫中各種資料項的一個程式執行單元)來保證資料的一致性和完整性。而在分散式系統中,資料一致性往往指的是由於資料的複製,不同資料節點中的資料內容是否完整並且相同。

為什麼會有資料一致性問題

初識分散式系統中我們介紹過,雖然分散式系統有著諸多優點,但是由於採用多機器進行分散式部署的方式提供服務,必然存在著資料的複製。分散式系統的資料複製需求主要來源於以下兩個原因:

可用性。將資料複製到分散式部署的多臺機器中,可以消除單點故障,防止系統由於某臺(些)機器當機導致的不可用。 效能。通過負載均衡技術,能夠讓分佈在不同地方的資料副本全都對外提供服務。有效提高系統效能。

在分散式系統引入複製機制後,不同的資料節點之間由於網路延時等原因很容易產生資料不一致的情況。複製機制的目的是為了保證資料的一致性。但是資料複製面臨的主要難題也是如何保證多個副本之間的資料一致性。


假設有這樣的場景,有兩個人同時去兩個不同的火車站買票(A去A火車站,B去B火車站),為了保證合理的賣票,需要在A火車站和B火車站之間共享關於剩餘票數的資料。但是A和B要買的票只剩下一張。一張票當然只能賣給一個人。 如果為了保證系統效能,那麼A和B在買票的時候應該都可以買票成功(因為他們在買票過程中餘票資料都顯示還有一張餘票)。兩人在買完票之後,系統在做資料複製時發現一張票被賣出了兩次,這時就要讓A和B兩人其中一人手中得票作廢掉。這時就要花費很大的力氣來通知後買到這張票的人這個訊息。。。 如果為了保證資料一致性,那麼就需要在A買票的過程中,B只能等著。等A買票結束,並且把餘票結果同步到B火車站的售票視窗。然後B才能知道還有沒有餘票可以購買。

上面的例子可以簡單的說明一個系統如果想保證資料一致性很有可能影響其效能。因為併發的寫請求需要在前一個寫請求結束之後才能進行。

因此,如何能既保證資料一致性,又保證系統的效能,是每一個分散式系統都需要重點考慮和權衡的。一致性模型可以在做這些權衡的時候給我們很多借鑑和思考。

一致性模型

強一致性

當更新操作完成之後,任何多個後續程式或者執行緒的訪問都會返回最新的更新過的值。這種是對使用者最友好的,就是使用者上一次寫什麼,下一次就保證能讀到什麼。但是這種實現對效能影響較大。

弱一致性

系統並不保證續程式或者執行緒的訪問都會返回最新的更新過的值。系統在資料寫入成功之後,不承諾立即可以讀到最新寫入的值,也不會具體的承諾多久之後可以讀到。但會盡可能保證在某個時間級別(比如秒級別)之後,可以讓資料達到一致性狀態。

最終一致性

弱一致性的特定形式。系統保證在沒有後續更新的前提下,系統最終返回上一次更新操作的值。在沒有故障發生的前提下,不一致視窗的時間主要受通訊延遲,系統負載和複製副本的個數影響。DNS是一個典型的最終一致性系統。

最終一致性模型的變種

因果一致性:如果A程式在更新之後向B程式通知更新的完成,那麼B的訪問操作將會返回更新的值。如果沒有因果關係的C程式將會遵循最終一致性的規則。

讀己所寫一致性:因果一致性的特定形式。一個程式總可以讀到自己更新的資料。

會話一致性:讀己所寫一致性的特定形式。程式在訪問儲存系統同一個會話內,系統保證該程式讀己之所寫。

單調讀一致性:如果一個程式已經讀取到一個特定值,那麼該程式不會讀取到該值以前的任何值。

單調寫一致性:系統保證對同一個程式的寫操作序列化。

上述最終一致性的不同方式可以進行組合,例如單調讀一致性和讀己之所寫一致性就可以組合實現。並且從實踐的角度來看,這兩者的組合,讀取自己更新的 資料,和一旦讀取到最新的版本不會再讀取舊版本,對於此架構上的程式開發來說,會少很多額外的煩惱。


為了解決分散式的一致性問題,在長期的研究探索過程中,湧現出了一大批經典的一致性協議和演算法,其中比較著名的有二階段提交協議,三階段提交協議和Paxos演算法。 下一篇文章將介紹這些和分散式一致性相關的協議和演算法。

相關文章