什么是分布式系統的CAP理論?

什么是分布式系統的CAP理論?

2000年7月,加州大學伯克利分校的Eric Brewer教授在ACM PODC會議上提出CAP猜想。2年后,麻省理工學院的Seth Gilbert和Nancy Lynch從理論上證明了CAP。之后,CAP理論正式成為分布式計算領域的公認定理。

無論你是一個系統架構師,還是一個普通開發,當你開發或者設計一個分布式系統的時候,CAP理論是無論如何也繞不過去的。本文就來介紹一下到底什么是CAP理論,如何證明CAP理論,以及CAP的權衡問題。

CAP理論概述

CAP理論:一個分布式系統最多只能同時滿足一致性(Consistency)、可用性(Availability)和分區容錯性(Partition tolerance)這三項中的兩項。
在這里插入圖片描述

讀者需要注意的的是,CAP理論中的CA和數據庫事務中ACID的CA并完全是同一回事兒。兩者之中的A都是C都是一致性(Consistency)。CAP中的A指的是可用性(Availability),而ACID中的A指的是原子性(Atomicity),切勿混為一談。

CAP的定義

Consistency 一致性

一致性指“all nodes see the same data at the same time”,即更新操作成功并返回客戶端完成后,所有節點在同一時間的數據完全一致,所以,一致性,說的就是數據一致性。

對于一致性,可以分為從客戶端和服務端兩個不同的視角。從客戶端來看,一致性主要指的是多并發訪問時更新過的數據如何獲取的問題。從服務端來看,則是更新如何復制分布到整個系統,以保證數據最終一致。

一致性是因為有并發讀寫才有的問題,因此在理解一致性的問題時,一定要注意結合考慮并發讀寫的場景。

從客戶端角度,多進程并發訪問時,更新過的數據在不同進程如何獲取的不同策略,決定了不同的一致性。

三種一致性策略

對于關系型數據庫,要求更新過的數據能被后續的訪問都能看到,這是強一致性。

如果能容忍后續的部分或者全部訪問不到,則是弱一致性。

如果經過一段時間后要求能訪問到更新后的數據,則是最終一致性。

CAP中說,不可能同時滿足的這個一致性指的是強一致性。

Availability 可用性

可用性指“Reads and writes always succeed”,即服務一直可用,而且是正常響應時間。

對于一個可用性的分布式系統,每一個非故障的節點必須對每一個請求作出響應。所以,一般我們在衡量一個系統的可用性的時候,都是通過停機時間來計算的。

可用性分類可用水平(%)年可容忍停機時間
容錯可用性99.9999<1 min
極高可用性99.999<5 min
具有故障自動恢復能力的可用性99.99<53 min
高可用性99.9<8.8h
商品可用性99<43.8 min

通常我們描述一個系統的可用性時,我們說淘寶的系統可用性可以達到5個9,意思就是說他的可用水平是99.999%,即全年停機時間不超過 (1-0.99999)*365*24*60 = 5.256 min,這是一個極高的要求。

好的可用性主要是指系統能夠很好的為用戶服務,不出現用戶操作失敗或者訪問超時等用戶體驗不好的情況。一個分布式系統,上下游設計很多系統如負載均衡、WEB服務器、應用代碼、數據庫服務器等,任何一個節點的不穩定都可以影響可用性。

Partition Tolerance分區容錯性

分區容錯性指“the system continues to operate despite arbitrary message loss or failure of part of the system”,即分布式系統在遇到某節點或網絡分區故障的時候,仍然能夠對外提供滿足一致性和可用性的服務。

分區容錯性和擴展性緊密相關。在分布式應用中,可能因為一些分布式的原因導致系統無法正常運轉。好的分區容錯性要求能夠使應用雖然是一個分布式系統,而看上去卻好像是在一個可以運轉正常的整體。比如現在的分布式系統中有某一個或者幾個機器宕掉了,其他剩下的機器還能夠正常運轉滿足系統需求,或者是機器之間有網絡異常,將分布式系統分隔未獨立的幾個部分,各個部分還能維持分布式系統的運作,這樣就具有好的分區容錯性。

簡單點說,就是在網絡中斷,消息丟失的情況下,系統如果還能正常工作,就是有比較好的分區容錯性。

CAP的證明

在這里插入圖片描述

如上圖,是我們證明CAP的基本場景,網絡中有兩個節點N1和N2,可以簡單的理解N1和N2分別是兩臺計算機,他們之間網絡可以連通,N1中有一個應用程序A,和一個數據庫V,N2也有一個應用程序B2和一個數據庫V。現在,A和B是分布式系統的兩個部分,V是分布式系統的數據存儲的兩個子數據庫。

在滿足一致性的時候,N1和N2中的數據是一樣的,V0=V0。在滿足可用性的時候,用戶不管是請求N1或者N2,都會得到立即響應。在滿足分區容錯性的情況下,N1和N2有任何一方宕機,或者網絡不通的時候,都不會影響N1和N2彼此之間的正常運作。

在這里插入圖片描述

如上圖,是分布式系統正常運轉的流程,用戶向N1機器請求數據更新,程序A更新數據庫Vo為V1,分布式系統將數據進行同步操作M,將V1同步的N2中V0,使得N2中的數據V0也更新為V1,N2中的數據再響應N2的請求。

這里,可以定義N1和N2的數據庫V之間的數據是否一樣為一致性;外部對N1和N2的請求響應為可用行;N1和N2之間的網絡環境為分區容錯性。這是正常運作的場景,也是理想的場景,然而現實是殘酷的,當錯誤發生的時候,一致性和可用性還有分區容錯性,是否能同時滿足,還是說要進行取舍呢?

作為一個分布式系統,它和單機系統的最大區別,就在于網絡,現在假設一種極端情況,N1和N2之間的網絡斷開了,我們要支持這種網絡異常,相當于要滿足分區容錯性,能不能同時滿足一致性和響應性呢?還是說要對他們進行取舍。

在這里插入圖片描述

假設在N1和N2之間網絡斷開的時候,有用戶向N1發送數據更新請求,那N1中的數據V0將被更新為V1,由于網絡是斷開的,所以分布式系統同步操作M,所以N2中的數據依舊是V0;這個時候,有用戶向N2發送數據讀取請求,由于數據還沒有進行同步,應用程序沒辦法立即給用戶返回最新的數據V1,怎么辦呢?

有兩種選擇:

  • 第一,犧牲數據一致性,保證可用性。響應舊的數據V0給用戶;
  • 第二,犧牲可用性,保證數據一致性。阻塞等待,直到網絡連接恢復,數據更新操作M完成之后,再給用戶響應最新的數據V1。

這個過程,證明了要滿足分區容錯性的分布式系統,只能在一致性和可用性兩者中,選擇其中一個。

CAP權衡

通過CAP理論及前面的證明,我們知道無法同時滿足一致性、可用性和分區容錯性這三個特性,那要舍棄哪個呢?

我們分三種情況來闡述一下。

CA without P

這種情況在分布式系統中幾乎是不存在的。首先在分布式環境下,網絡分區是一個自然的事實。因為分區是必然的,所以如果舍棄P,意味著要舍棄分布式系統。那也就沒有必要再討論CAP理論了。這也是為什么在前面的CAP證明中,我們以系統滿足P為前提論述了無法同時滿足C和A。

比如我們熟知的關系型數據庫,如My Sql和Oracle就是保證了可用性和數據一致性,但是他并不是個分布式系統。一旦關系型數據庫要考慮主備同步、集群部署等就必須要把P也考慮進來。

其實,在CAP理論中。C,A,P三者并不是平等的,CAP之父在《Spanner,真時,CAP理論》一文中寫到:

如果說Spanner真有什么特別之處,那就是谷歌的廣域網。Google通過建立私有網絡以及強大的網絡工程能力來保證P,在多年運營改進的基礎上,在生產環境中可以最大程度的減少分區發生,從而實現高可用性。

從Google的經驗中可以得到的結論是,無法通過降低CA來提升P。要想提升系統的分區容錯性,需要通過提升基礎設施的穩定性來保障。

所以,對于一個分布式系統來說。P是一個基本要求,CAP三者中,只能在CA兩者之間做權衡,并且要想盡辦法提升P。

CP without A

如果一個分布式系統不要求強的可用性,即容許系統停機或者長時間無響應的話,就可以在CAP三者中保障CP而舍棄A。

一個保證了CP而一個舍棄了A的分布式系統,一旦發生網絡故障或者消息丟失等情況,就要犧牲用戶的體驗,等待所有數據全部一致了之后再讓用戶訪問系統。

設計成CP的系統其實也不少,其中最典型的就是很多分布式數據庫,他們都是設計成CP的。在發生極端情況時,優先保證數據的強一致性,代價就是舍棄系統的可用性。如Redis、HBase等,還有分布式系統中常用的Zookeeper也是在CAP三者之中選擇優先保證CP的。

無論是像Redis、HBase這種分布式存儲系統,還是像Zookeeper這種分布式協調組件。數據的一致性是他們最最基本的要求。一個連數據一致性都保證不了的分布式存儲要他有何用?

ZooKeeper是個CP(一致性+分區容錯性)的,即任何時刻對ZooKeeper的訪問請求能得到一致的數據結果,同時系統對網絡分割具備容錯性。但是它不能保證每次服務請求的可用性,也就是在極端環境下,ZooKeeper可能會丟棄一些請求,消費者程序需要重新請求才能獲得結果。ZooKeeper是分布式協調服務,它的職責是保證數據在其管轄下的所有服務之間保持同步、一致。所以就不難理解為什么ZooKeeper被設計成CP而不是AP特性的了。

AP wihtout C

要高可用并允許分區,則需放棄一致性。一旦網絡問題發生,節點之間可能會失去聯系。為了保證高可用,需要在用戶訪問時可以馬上得到返回,則每個節點只能用本地數據提供服務,而這樣會導致全局數據的不一致性。

這種舍棄強一致性而保證系統的分區容錯性和可用性的場景和案例非常多。前面我們介紹可用性的時候說到過,很多系統在可用性方面會做很多事情來保證系統的全年可用性可以達到N個9,所以,對于很多業務系統來說,比如淘寶的購物,12306的買票。都是在可用性和一致性之間舍棄了一致性而選擇可用性。

你在12306買票的時候肯定遇到過這種場景,當你購買的時候提示你是有票的(但是可能實際已經沒票了),你也正常的去輸入驗證碼,下單了。但是過了一會系統提示你下單失敗,余票不足。這其實就是先在可用性方面保證系統可以正常的服務,然后在數據的一致性方面做了些犧牲,會影響一些用戶體驗,但是也不至于造成用戶流程的嚴重阻塞。

但是,我們說很多網站犧牲了一致性,選擇了可用性,這其實也不準確的。就比如上面的買票的例子,其實舍棄的只是強一致性。退而求其次保證了最終一致性。也就是說,雖然下單的瞬間,關于車票的庫存可能存在數據不一致的情況,但是過了一段時間,還是要保證最終一致性的。

對于多數大型互聯網應用的場景,主機眾多、部署分散,而且現在的集群規模越來越大,所以節點故障、網絡故障是常態,而且要保證服務可用性達到N個9,即保證P和A,舍棄C(退而求其次保證最終一致性)。雖然某些地方會影響客戶體驗,但沒達到造成用戶流程的嚴重程度。

適合的才是最好的

上面介紹了如何CAP中權衡及取舍以及典型的案例。孰優孰略,沒有定論,只能根據場景定奪,適合的才是最好的。

對于涉及到錢財這樣不能有一絲讓步的場景,C必須保證。網絡發生故障寧可停止服務,這是保證CP,舍棄A。比如前幾年支付寶光纜被挖斷的事件,在網絡出現故障的時候,支付寶就在可用性和數據一致性之間選擇了數據一致性,用戶感受到的是支付寶系統長時間宕機,但是其實背后是無數的工程師在恢復數據,保證數數據的一致性。

對于其他場景,比較普遍的做法是選擇可用性和分區容錯性,舍棄強一致性,退而求其次使用最終一致性來保證數據的安全。這其實是分布式領域的另外一個理論——BASE理論。我們下一篇文章再來介紹。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/536047.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/536047.shtml
英文地址,請注明出處:http://en.pswp.cn/news/536047.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

什么是分布式系統的BASE理論?

什么是分布式系統的BASE理論&#xff1f; BASE理論 eBay的架構師Dan Pritchett源于對大規模分布式系統的實踐總結&#xff0c;在ACM上發表文章提出BASE理論&#xff0c;BASE理論是對CAP理論的延伸&#xff0c;核心思想是即使無法做到強一致性&#xff08;Strong Consistency&a…

Docker教程介紹

Docker教程介紹 教程環境準備 linux 系統virtualbox 軟件安裝 教程介紹 0-安裝Vagrant&#xff0c;安裝 centos 系統。1-docker 介紹2-docker 安裝3-docker 架構和底層技術簡介4-什么是Image和container5-Dockerfile文件6-搭建一個私有registry7-深入練習Dockerfile8-容器操…

1-docker 介紹

1-docker 介紹 由PaaS到Container 2013年2月&#xff0c;前Gluster的CEO Ben Golub 和 dotCloud 的 CEO Solomon Hykes 坐在一起聊天時&#xff0c;Solomon談到想把 dotCloud 內部使用的Container容器技術單獨拿出來開源&#xff0c;然后圍繞這個技術開一家新公司提供技術支持…

3-docker 架構和底層技術簡介

3-docker 架構和底層技術簡介 Docker Platform Docker 是一個平臺。 提供了一個開發、打包、運行app的平臺把app和底層 infrastructure 隔離開來 根據上圖我們可以看出 Docker Engine 把上層的 app 應用程序和底層的物理設備或虛擬設備進行了隔離&#xff0c;然后我們在 doc…

4-什么是Image和container

4-什么是Image和container 什么是Image? 先練習一個例子: docker pull ubuntu:16.04 docker image ls # 查看鏡像鏡像類似于一個系統安裝光盤&#xff0c;你可以使用一個安裝光盤為多臺電腦安裝操作系統&#xff0c;同樣&#xff0c;你也可以用同一個鏡像構建多個運行的…

5-Dockerfile文件

5-Dockerfile文件 先練習一個例子: 創建 Dockerfile 文件 FROM ubuntu:14.04 LABEL maintainer"vincent <jeffmanwordgmail.com>" RUN apt-get update && apt-get install -y redis-server EXPOSE 6397 ENTRYPOINT [ "/usr/bin/redis-server&quo…

6-搭建一個私有registry

6-搭建一個私有registry docker hub 查找 registry docker hub registry 可以看到部署很簡單&#xff0c;只有一條命令。 docker run -d -p 5000:5000 --restart always --name registry registry:2部署私有registry 找一臺linux的服務器并安裝好docker 在此服務器上部署re…

7-深入練習Dockerfile

7-深入練習Dockerfile 創建一個json-server 鏡像 首先創建一個 json-server 文件夾 mkdir json-server在json-server文件夾下創建Dockerfile FROM node:10.15.0 RUN npm install -g json-server構建鏡像 docker build -t json-server .創建一個api服務的鏡像 首先創建一個 …

8-容器操作

8-容器操作 普通操作 進入容器 docker exec -it api /bin/bash容器停止與啟動 docker stop api docker start api容器重啟 docker restart api查看容器詳細信息 docker inspect api查看日志 docker logs api容器刪除 docker stop api # 必須先停止才能刪除 docker rm…

9-資源限制

9-資源限制 了解stress工具 stress是一個壓力測試工具 docker run -it ubuntu:16.04此時會進入ubuntu內&#xff0c;這時我們安裝 stress工具 apt-get update && apt-get install -y stress查看help stress --helpUsage: stress [OPTION [ARG]] ...-?, --help …

10-Docker 網絡

10-Docker 網絡 基礎網絡概念 數據傳輸通過數據包 兩臺筆記本之間通信是通過數據包通信的。想知道數據包是怎么打包的呢&#xff0c;就先要知道網絡分層的概念。 網絡分層 目前有兩種網絡分層的模型。 ISO/OSI 分層&#xff0c;也就是 7 層模型。TCP/IP 分層&#xff0c;也就…

11-Docker Bridge詳解

11-Docker Bridge詳解 容器之間是如何通信的&#xff1f; 操作前刪除test2的容器。 查看當前機器上docker的網絡 docker network lsNETWORK ID NAME DRIVER SCOPE 056d0ece100f bridge bridge local a…

12-容器之間link

12-容器之間link 這篇主要講 容器之間如何 link。 需要準備的是&#xff0c;創建兩個容器 test1 和 test2 通過 busybox。 在之前的課程中已經創建的只需要重新啟動即可。 什么情況下需要link 例如有一個容器是 web 服務器&#xff0c;并且跑在一個docker容器內&#xff0c;…

13-容器的端口映射

13-容器的端口映射 部署一個簡單web nginx容器 docker run -d --name web nginxnginx 默認的端口是 80 端口&#xff0c;此時我們是沒有辦法訪問的。 好的&#xff0c;通過前面的學習我們已經知道&#xff0c;這個 web 容器四連接到 bridge 網橋上的&#xff0c;那我們查看一…

14-容器網絡之host和none

14-容器網絡之host和none 在之前的小節&#xff0c;我們有看到過 host 和 none。 通過 docker network ls 查看。 none 網絡 刪除 test1 容器 docker stop test1 && docker rm test1創建 test1 容器并連接到none網絡 docker run -d --name test1 --network none busy…

15-多容器復雜應用的部署

15-多容器復雜應用的部署 此節主要是通過部署一個復雜的應用場景&#xff0c;進而練習容器的網絡相關知識。 創建一個flask-web應用 創建一個 flask-web 文件夾 mkdir flask-web在此文件夾內創建 app.py 文件 cd flask-web touch app.py編寫一個簡單的 web 程序 import os im…

16-多機器通信

16-多機器通信 回顧上節課的思考題。 flask-redis 想訪問 redis&#xff0c;該如何通信&#xff1f; 創建另外一臺linux虛擬機 直接拷貝Vagrantfile文件創建一個 centos 虛擬機 我們創建一個centos7-2文件夾&#xff0c;然后創建虛擬機 vagrant up創建的過程中提示選擇網絡接…

17-Docker的數據持久化介紹

17-Docker的數據持久化介紹 回顧容器與鏡像 容器是在鏡像之上創建的一層運行時層&#xff0c;這一層是可以讀寫的&#xff0c;我們能夠在容器內添加數據&#xff0c;讀取數據。 也就是說我們在創建容器的時候&#xff0c;我們能夠在容器內創建文件&#xff0c;安裝軟件等等&a…

18-數據持久化-Data Volume

18-數據持久化-Data Volume Data Volume 使用場景。一般來講有些容器自己會產生一些數據&#xff0c;我們不想數據隨著容器的銷毀而銷毀&#xff0c;我們想保存數據&#xff0c;正常一般用在數據庫&#xff0c;比如我們想保存數據庫中的數據&#xff0c;這個時候我們就會使用 …

19-數據持久化-Bind Mounting

19-數據持久化-Bind Mounting Bind Mounting 與 Data Volume區別 Data Volume 需要在 Dockerfile 內聲明需要創建的 volume 目錄。 Bind Mounting 則不需要在 Dockerfile 聲明 volume&#xff0c;只需要在創建容器的時候&#xff0c;也就是 run 的時候聲明即可。 如: dock…