一、引言
數據一致性的重要性?
分布式領域CAP理論告訴我們,任何一個分布式系統都無法同時滿足Consistency(一致性),Availability(可用性), Partition tolerance(分區容錯性) 這三個基本需求。最多只能滿足其中兩項。 但是,一個分布式系統無論在CAP三者之間如何權衡,都無法徹底放棄一致性(Consistency),如果真的放棄一致性,那么就說明這個系統中的數據根本不可信,數據也就沒有意義,那么這個系統也就沒有任何價值可言。所以,無論如何,分布式系統的一致性問題都需要重點關注。
由於一個分布式系統不可能放棄一致性,那么為什么有的架構師還說在某些場景中可以犧牲一致性呢?通常這里說的放棄一致性指的是放棄數據的強一致性。
通常情況下,我們所說的分布式一致性問題通常指的是數據一致性問題。那么我們就先來了解一下什么是數據一致性。
二、數據一致性
數據一致性其實是數據庫系統中的概念。我們可以簡單的把一致性理解為正確性或者完整性,那么數據一致性通常指關聯數據之間的邏輯關系是否正確和完整。我們知道,在數據庫系統中通常用事務(訪問並可能更新數據庫中各種數據項的一個程序執行單元)來保證數據的一致性和完整性。而在分布式系統中,數據一致性往往指的是由於數據的復制,不同數據節點中的數據內容是否完整並且相同。
比如在集中式系統中,有一些關鍵的配置信息,可以直接保存在服務器的內存中,但是在分布式系統中,如何保存這些配置信息,又如何保證所有機器上的配置信息都保持一致,又如何保證修改一個配置能夠把這次修改同步到所有機器中呢?
再比如,在集中式系統中,進行一個同步操作要寫同一個數據的時候,可以直接使用事務+鎖來管理保證數據的ACID。但是,在分布式系統中如何保證多台機器不會同時寫同一條數據呢?
三、為什么會有數據一致性問題
雖然分布式系統有着諸多優點,但是由於采用多機器進行分布式部署的方式提供服務,必然存在着數據的復制。分布式系統的數據復制需求主要來源於以下兩個原因:
1、可用性:將數據復制到分布式部署的多台機器中,可以消除單點故障。防止系統由於某些機器宕機導致的不可用。
2、性能:通過負載均衡技術,能夠讓分布在不同地方的數據副本全都對外提供服務。有效提高系統性能。
在分布式系統引入復制機制后,不同的數據節點之間由於網絡延時等原因很容易產生數據不一致和數據復制延遲(單獨一篇文章詳細說明復制延遲的解決方案)的情況。復制機制的目的是為了保證數據的一致性。但是數據復制面臨的主要難題也是如何保證多個副本之間的數據一致性。
假設有這樣的場景,有兩個人同時去兩個不同的火車站買票(A去A火車站,B去B火車站),為了保證合理的賣票,需要在A火車站和B火車站之間共享關於剩余票數的數據。但是A和B要買的票只剩下一張。一張票當然只能賣給一個人。 如果為了保證系統性能,那么A和B在買票的時候應該都可以買票成功(因為他們在買票過程中余票數據都顯示還有一張余票)。兩人在買完票之后,系統在做數據復制時發現一張票被賣出了兩次,這時就要讓A和B兩人其中一人手中得票作廢掉。這時就要花費很大的力氣來通知后買到這張票的人這個消息。。。 如果為了保證數據一致性,那么就需要在A買票的過程中,B只能等着。等A買票結束,並且把余票結果同步到B火車站的售票窗口。然后B才能知道還有沒有余票可以購買。
上面的例子可以簡單的說明一個系統如果想保證數據一致性很有可能影響其性能。因為並發的寫請求需要在前一個寫請求結束之后才能進行。
因此,如何能既保證數據一致性,又保證系統的性能,是每一個分布式系統都需要重點考慮和權衡的。一致性模型可以在做這些權衡的時候給我們很多借鑒和思考。
四、一致性模型
1、強一致性
當更新操作完成之后,任何多個后續進程或者線程的訪問都會返回最新的更新過的值。這種是對用戶最友好的,就是用戶上一次寫什么,下一次就保證能讀到什么。但是這種實現對性能影響較大。
2、弱一致性
系統並不保證續進程或者線程的訪問都會返回最新的更新過的值。系統在數據寫入成功之后,不承諾立即可以讀到最新寫入的值,也不會具體的承諾多久之后可以讀到。但會盡可能保證在某個時間級別(比如秒級別)之后,可以讓數據達到一致性狀態。
3、最終一致性
弱一致性的特定形式。系統保證在沒有后續更新的前提下,系統最終返回上一次更新操作的值。在沒有故障發生的前提下,不一致窗口的時間主要受通信延遲,系統負載和復制副本的個數影響。DNS是一個典型的最終一致性系統。
4、最終一致性模型的變種
- 因果一致性:如果A進程在更新之后向B進程通知更新的完成,那么B的訪問操作將會返回更新的值。如果沒有因果關系的C進程將會遵循最終一致性的規則。
- 讀己所寫一致性:因果一致性的特定形式。一個進程總可以讀到自己更新的數據。
- 會話一致性:讀己所寫一致性的特定形式。進程在訪問存儲系統同一個會話內,系統保證該進程讀己之所寫。
- 單調讀一致性:如果一個進程已經讀取到一個特定值,那么該進程不會讀取到該值以前的任何值。
- 單調寫一致性:系統保證對同一個進程的寫操作串行化。
上述最終一致性的不同方式可以進行組合,例如單調讀一致性和讀己之所寫一致性就可以組合實現。並且從實踐的角度來看,這兩者的組合,讀取自己更新的數據,和一旦讀取到最新的版本不會再讀取舊版本,對於此架構上的程序開發來說,會少很多額外的煩惱。
為了解決分布式的一致性問題,在長期的研究探索過程中,涌現出了一大批經典的一致性協議和算法,其中比較著名的有二階段提交協議,三階段提交協議和Paxos算法。
參考
