關於分佈式系統的思考

摘要

談及一些分佈式系統的理論和思想,包括CAP、BASE、NWR等。並簡單分析一些主流數據庫分佈式方案的利弊,以便咱們在開發時更深刻全面地進行思考、選擇和設計。數據庫

正文

在討論常見架構前,先簡單瞭解下CAP理論: 微信

CAP 是 Consistency、Availablity 和 Partition-tolerance 的縮寫。分別是指:網絡

  1. 一致性(Consistency):每次讀操做都能保證返回的是最新數據;架構

  2. 可用性(Availablity):任何一個沒有發生故障的節點,會在合理的時間內返回一個正常的結果;異步

  3. 分區容忍性(Partition-tolerance):當節點間出現網絡分區,照樣能夠提供服務。分佈式

CAP理論指出:CAP三者只能取其二,不可兼得。其實這一點很好理解:微服務

  • 首先,單機系統都只能保證CP。性能

  • 有兩個或以上節點時,當網絡分區發生時,集羣中兩個節點不能互相通訊。此時若是保證數據的一致性C,那麼必然會有一個節點被標記爲不可用的狀態,違反了可用性A的要求,只能保證CP。spa

  • 反之,若是保證可用性A,即兩個節點能夠繼續各自處理請求,那麼因爲網絡不通不能同步數據,必然又會致使數據的不一致,只能保證AP。設計

cas

1、單實例

單機系統很顯然,只能保證CP,犧牲了可用性A。單機版的MySQL,Redis,MongoDB等數據庫都是這種模式。

single

實際中,咱們須要一套可用性高的系統,即便部分機器掛掉以後仍然能夠繼續提供服務。

2、多副本

multi

相比於單實例,這裏多了一個節點去備份數據。

對於讀操做來講,由於能夠訪問兩個節點中的任意一個,因此可用性提高。

對於寫操做來講,根據更新策略分爲三種狀況:

  1. 同步更新:即寫操做須要等待兩個節點都更新成功才返回。這樣的話若是一旦發生網絡分區故障,寫操做便不可用,犧牲了A。

  2. 異步更新:即寫操做直接返回,不須要等待節點更新成功,節點異步地去更新數據。
    這種方式,犧牲了C來保證A。即沒法保證數據是否更新成功,還有可能會因爲網絡故障等緣由,致使數據不一致。

  3. 折衷:更新部分節點成功後便返回。

這裏,先介紹下類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模式,是弱一致性的。

nwr

舉例:

  • 如像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的提升。並且,會產生‘腦裂’的問題——即網絡分區時節點各自處理請求,沒法同步數據,當網絡恢復時,致使不一致。

通常的,數據庫都會提供分區恢復的解決方案:

  1. 從源頭解決:如設定節點通訊的超時時間,超時後‘少數派’節點不提供服務。這樣便不會出現數據不一致的狀況,不過可用性下降。

  2. 從恢復解決:如在通訊恢復時,對不一樣節點的數據進行比較、合併,這樣可用性獲得了保證。可是在恢復完成以前,數據是不一致的,並且可能出現數據衝突。

光這樣還不夠,當數據量較大時,因爲一臺機器的資源有限並不能容納全部的數據,咱們會想把數據分到好幾臺機器上存儲。

3、分片

sharding

相比於單實例,這裏多了一個節點去分割數據。

因爲全部數據都只有一份,一致性得以保證;節點間不須要通訊,分區容忍性也有。

然而,當任意一個節點掛掉,丟失了一部分的數據,系統可用性得不到保證。

綜上,這和單機版的方案同樣,都只能保證CP。

那麼,有那些好處呢?

  1. 某個節點掛掉只會影響部分服務,即服務降級;

  2. 因爲分片了數據,能夠均衡負載;

  3. 數據量增大/減少後能夠相應地擴容/縮容。

    大多數的數據庫服務都提供了分片的功能。如Redis的slots,Cassandra的partitions,MongoDB的shards等。

基於分片解決了數據量大的問題,但是咱們仍是但願咱們的系統是高可用的,那麼,如何犧牲必定的一致性去保證可用性呢?

4、集羣

clustercluster2

能夠看到,上面這種方式綜合了前兩種方式。同上分析,採用不一樣的數據同步策略,系統的CAP保證各有不一樣。不過,通常數據庫系統都會提供可選的配置,咱們根據不一樣的場景選擇不一樣的策略以實現不一樣的特性。

其實,對於大多數的非金融類互聯網公司,要求並不是強一致性,而是可用性和最終一致性的保證。這也是NoSQL流行於互聯網應用的一大緣由,相比於強一致性系統的ACID原則,它更加傾向於BASE

  • Basically Available: 基本可用,即容許分區失敗,出了問題僅服務降級;

  • Soft-state: 軟狀態,即容許異步;

  • Eventual Consistency: 最終一致性,容許數據最終一致,而不是時刻一致。

5、總結

基本上,上面討論的幾種方式已經涵蓋了大多數的分佈式存儲系統了。咱們能夠看到,這些個方案老是須要經過犧牲一部分去換取另外一部分,總無法達到100%的CAP。

選擇哪一種方案,依據就是在特定場景下,究竟哪些特性是更加劇要的了。


做者信息
本文系力譜宿雲LeapCloud旗下MaxLeap團隊_Service&Infra成員:呂舜 【原創】
力譜宿雲LeapCloud 首發:https://blog.maxleap.cn/archi...
呂舜,主攻Java,對Python、數據分析也有關注。從業期間,負責過訂閱系統、App製做雲服務、開源BaaS平臺、分佈式任務調度系統等產品的設計研發工做。現任MaxLeap基礎服務與架構成員,負責雲服務系統相關的設計與開發。

相關閱讀

微服務實戰:從架構到發佈(一)
微服務實戰:從架構到發佈(二)
移動雲平臺的基礎架構之旅(一):雲應用
從應用到平臺 – 雲服務架構的演進過程

做者往期佳做_曾選登CSDN頭版

RabbitMQ在分佈式系統的應用

歡迎關注微信公衆號:MaxLeap_yidongyanfa


活動預告

clipboard.png

報名連接:http://t.cn/Rt9ooRw

相關文章
相關標籤/搜索