談及一些分佈式系統的理論和思想,包括CAP、BASE、NWR等。並簡單分析一些主流數據庫分佈式方案的利弊,以便咱們在開發時更深刻全面地進行思考、選擇和設計。數據庫
在討論常見架構前,先簡單瞭解下CAP理論: 微信
CAP 是 Consistency、Availablity 和 Partition-tolerance 的縮寫。分別是指:網絡
一致性(Consistency):每次讀操做都能保證返回的是最新數據;架構
可用性(Availablity):任何一個沒有發生故障的節點,會在合理的時間內返回一個正常的結果;異步
分區容忍性(Partition-tolerance):當節點間出現網絡分區,照樣能夠提供服務。分佈式
CAP理論指出:CAP三者只能取其二,不可兼得。其實這一點很好理解:微服務
首先,單機系統都只能保證CP。性能
有兩個或以上節點時,當網絡分區發生時,集羣中兩個節點不能互相通訊。此時若是保證數據的一致性C,那麼必然會有一個節點被標記爲不可用的狀態,違反了可用性A的要求,只能保證CP。spa
反之,若是保證可用性A,即兩個節點能夠繼續各自處理請求,那麼因爲網絡不通不能同步數據,必然又會致使數據的不一致,只能保證AP。設計
單機系統很顯然,只能保證CP,犧牲了可用性A。單機版的MySQL,Redis,MongoDB等數據庫都是這種模式。
實際中,咱們須要一套可用性高的系統,即便部分機器掛掉以後仍然能夠繼續提供服務。
相比於單實例,這裏多了一個節點去備份數據。
對於讀操做來講,由於能夠訪問兩個節點中的任意一個,因此可用性提高。
對於寫操做來講,根據更新策略分爲三種狀況:
同步更新:即寫操做須要等待兩個節點都更新成功才返回。這樣的話若是一旦發生網絡分區故障,寫操做便不可用,犧牲了A。
異步更新:即寫操做直接返回,不須要等待節點更新成功,節點異步地去更新數據。
這種方式,犧牲了C來保證A。即沒法保證數據是否更新成功,還有可能會因爲網絡故障等緣由,致使數據不一致。
折衷:更新部分節點成功後便返回。
這裏,先介紹下類Dynamo系統用於控制分佈式存儲系統中的一致性級別的策略——NWR:
N:同一份數據的副本個數
W:寫操做須要確保成功的副本個數
R:讀操做須要讀取的副本個數
當W+R>N時,因爲讀寫操做覆蓋到的副本集確定會有交集,讀操做只要比較副本集數據的修改時間或者版本號便可選出最新的,因此係統是強一致性的;反之,當W+R<=N時是弱一致性的。
如:(N,W,R)=(1,1,1)爲單機系統,是強一致性的;(N,W,R)=(2,1,1)爲常見的master-slave模式,是弱一致性的。
舉例:
如像Cassandra中的折衷型方案QUORUM
,只要超過半數的節點更新成功便返回,讀取時返回多數副本的一致的值。而後,對於不一致的副本,能夠經過read repair的方式解決。 read repair
:讀取某條數據時,查詢全部副本中的這條數據,比較數據與大多數副本的最新數據是否一致,若否,則進行一致性修復。其中,W+R>N,故而是強一致性的。
又如Redis的master-slave模式,更新成功一個節點即返回,其餘節點異步地去備份數據。這種方式只保證了最終一致性。 最終一致性
:相比於數據時刻保持一致的強一致性,最終一致性容許某段時間內數據不一致。可是隨着時間的增加,數據最終會到達一致的狀態。其中,W+R<N,因此只能保證最終一致性。
此外,N越大,數據可靠性越好。可是因爲W或R越大,寫或讀開銷越大,性能越差,因此通常須要綜合考慮一致性、可用性和讀寫性能,設置 W、R 都爲 N/2 + 1。
其實,折衷方案和異步更新的方式從本質上來講是同樣的,都是損失必定的C來換取A的提升。並且,會產生‘腦裂’的問題——即網絡分區時節點各自處理請求,沒法同步數據,當網絡恢復時,致使不一致。
通常的,數據庫都會提供分區恢復的解決方案:
從源頭解決:如設定節點通訊的超時時間,超時後‘少數派’節點不提供服務。這樣便不會出現數據不一致的狀況,不過可用性下降。
從恢復解決:如在通訊恢復時,對不一樣節點的數據進行比較、合併,這樣可用性獲得了保證。可是在恢復完成以前,數據是不一致的,並且可能出現數據衝突。
光這樣還不夠,當數據量較大時,因爲一臺機器的資源有限並不能容納全部的數據,咱們會想把數據分到好幾臺機器上存儲。
相比於單實例,這裏多了一個節點去分割數據。
因爲全部數據都只有一份,一致性得以保證;節點間不須要通訊,分區容忍性也有。
然而,當任意一個節點掛掉,丟失了一部分的數據,系統可用性得不到保證。
綜上,這和單機版的方案同樣,都只能保證CP。
那麼,有那些好處呢?
某個節點掛掉只會影響部分服務,即服務降級;
因爲分片了數據,能夠均衡負載;
數據量增大/減少後能夠相應地擴容/縮容。
大多數的數據庫服務都提供了分片的功能。如Redis的slots,Cassandra的partitions,MongoDB的shards等。
基於分片解決了數據量大的問題,但是咱們仍是但願咱們的系統是高可用的,那麼,如何犧牲必定的一致性去保證可用性呢?
能夠看到,上面這種方式綜合了前兩種方式。同上分析,採用不一樣的數據同步策略,系統的CAP保證各有不一樣。不過,通常數據庫系統都會提供可選的配置,咱們根據不一樣的場景選擇不一樣的策略以實現不一樣的特性。
其實,對於大多數的非金融類互聯網公司,要求並不是強一致性,而是可用性和最終一致性的保證。這也是NoSQL流行於互聯網應用的一大緣由,相比於強一致性系統的ACID原則,它更加傾向於BASE:
Basically Available
: 基本可用,即容許分區失敗,出了問題僅服務降級;
Soft-state
: 軟狀態,即容許異步;
Eventual Consistency
: 最終一致性,容許數據最終一致,而不是時刻一致。
基本上,上面討論的幾種方式已經涵蓋了大多數的分佈式存儲系統了。咱們能夠看到,這些個方案老是須要經過犧牲一部分去換取另外一部分,總無法達到100%的CAP。
選擇哪一種方案,依據就是在特定場景下,究竟哪些特性是更加劇要的了。
做者信息
本文系力譜宿雲LeapCloud旗下MaxLeap團隊_Service&Infra成員:呂舜 【原創】
力譜宿雲LeapCloud 首發:https://blog.maxleap.cn/archi...
呂舜,主攻Java,對Python、數據分析也有關注。從業期間,負責過訂閱系統、App製做雲服務、開源BaaS平臺、分佈式任務調度系統等產品的設計研發工做。現任MaxLeap基礎服務與架構成員,負責雲服務系統相關的設計與開發。
相關閱讀
微服務實戰:從架構到發佈(一)
微服務實戰:從架構到發佈(二)
移動雲平臺的基礎架構之旅(一):雲應用
從應用到平臺 – 雲服務架構的演進過程
做者往期佳做_曾選登CSDN頭版
歡迎關注微信公衆號:MaxLeap_yidongyanfa
活動預告
報名連接:http://t.cn/Rt9ooRw