天道不一定酬所有勤
但是,天道只酬勤

關于分布式一致性的探究

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

一致性的重要性

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

這里先簡單提一下,由于一個分布式系統不可能放棄一致性,那么為什么有的架構師還說在某些場景中可以犧牲一致性呢?通常這里說的放棄一致性指的是放棄數據的強一致性(后文介紹什么是強一致性)。

通常情況下,我們所說的分布式一致性問題通常指的是數據一致性問題。那么我們就先來了解一下什么是數據一致性。

數據一致性

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

?比如在集中式系統中,有一些關鍵的配置信息,可以直接保存在服務器的內存中,但是在分布式系統中,如何保存這些配置信息,又如何保證所有機器上的配置信息都保持一致,又如何保證修改一個配置能夠把這次修改同步到所有機器中呢?

再比如,在集中式系統中,進行一個同步操作要寫同一個數據的時候,可以直接使用事務+鎖來管理保證數據的ACID。但是,在分布式系統中如何保證多臺機器不會同時寫同一條數據呢?

除了上面提到的同一個數據的一致性,還有一種情況也可以叫做數據的一致性:比如我們在電商網站下單,需要經歷扣減庫存、扣減紅包、扣減折扣券等一系列操作。如果庫存庫存扣減成功,但是紅包和折扣券扣減失敗的話,也可以說是數據沒有保證一致性。

如何保證數據的一致性,是分布式系統中必須面對的問題。

為什么會有數據一致性問題

初識分布式系統中我們介紹過,雖然分布式系統有著諸多優點,但是由于采用多機器進行分布式部署的方式提供服務,必然存在著數據的復制(如數據庫的異地容災,多地部署)。分布式系統的數據復制需求主要來源于以下兩個原因:

可用性。將數據復制到分布式部署的多臺機器中,可以消除單點故障。防止系統由于某臺(些)機器宕機導致的不可用。

性能。通過負載均衡技術,能夠讓分布在不同地方的數據副本全都對外提供服務。有效提高系統性能。

分布式系統為了提升可用性和性能,會通過復制技術來進行數據同步。復制機制的目的是為了保證數據的一致性。但是數據復制面臨的主要難題也是如何保證多個副本之間的數據一致性。在分布式系統引入復制機制后,不同的數據節點之間由于網絡延時等原因很容易產生數據不一致的情況。

如果上面提到的數據復制場景你不是很熟悉的話,下面這個例子你肯定遇到過。就是現在很多網站都是微服務化的,一個網站被垂直拆分成多個功能模塊。各模塊之間獨立部署。模塊間通過RPC或者HTTP交互。由于這種RPC或者HTTP的交互可能存在網絡延遲導致超時的情況。甚至被調用方也有可能執行出錯等情況,這時候就可能導致數據不一致。

比如下單操作要依次扣減紅包、扣減折扣券、扣減庫存。在下單應用的執行過程中,調用紅包系統扣減紅包成功了,但是再調用折扣券系統扣減折扣券的時候網絡超時了。這時候下單應用根本不知道折扣券系統到底有沒有執行成功。這時候他就需要一些機制來決定是要回滾紅包的扣減,還是繼續執行庫存的扣減。這種機制,其實就是數據一致性的解決方案了。

由于應用分布式部署,就無法通過數據庫事務保證多個寫操作的原子性。一旦某個操作失敗,其他操作如果不回滾的話就會發生數據不一致問題。

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

一致性模型

強一致性

當更新操作完成之后,任何多個后續進程或者線程的訪問都會返回最新的更新過的值。這種是對用戶最友好的,就是用戶上一次寫什么,下一次就保證能讀到什么。

但是這種實現對性能影響較大,因為這意味著,只要上次的操作沒有處理完,就不能讓用戶讀取數據。

弱一致性

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

最終一致性

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

最終一致性模型的變種

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

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

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

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

單調寫一致性:系統保證對同一個進程的寫操作串行化。

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

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

(全文完) 歡迎關注『Java之道』微信公眾號
贊(17)
如未加特殊說明,此網站文章均為原創,轉載必須注明出處。HollisChuang's Blog » 關于分布式一致性的探究
分享到: 更多 (0)

評論 2

  • 昵稱 (必填)
  • 郵箱 (必填)
  • 網址
  1. #1

    很棒。學習到了。

    灰煙飛4年前 (2015-12-06)回復
    • 學習到了

      果凍想4年前 (2015-12-08)回復

HollisChuang's Blog

聯系我關于我
网上设计赚钱的网站有哪些