一文聊透CAP定理
很多同學(xué)都知道,在一個(gè)分布式系統(tǒng)中,最多只能在一致性(Consistency)、可用性(Availability)和分區(qū)容錯(cuò)性(Partition tolerance)中三者滿足其二,不能同時(shí)滿足這三項(xiàng)。
CAP定理
圖片
一致性(Consistency),all nodes see the same data at the same time,按照原文翻譯是:在同一時(shí)刻,分布式系統(tǒng)中所有節(jié)點(diǎn)中的數(shù)據(jù)是完全一致的。
我們也可以引申理解為“分布式系統(tǒng)的業(yè)務(wù)邏輯一致性”。
舉個(gè)例子:用戶 A 給用戶 B 轉(zhuǎn)賬 100 元,那么在任何時(shí)刻,我們都必須能夠同時(shí)看到用戶 A 的賬戶少了 100 元,用戶 B 的賬戶多了 100 元。
一致性分為強(qiáng)一致性、弱一致性和最終一致性。
- 強(qiáng)一致性,業(yè)務(wù)結(jié)果中的每個(gè)步驟,在“任何時(shí)刻”都同時(shí)生效。CAP 定理中所說的一致性就是強(qiáng)一致性,上述例子中所描述的也是強(qiáng)一致性。
- 弱一致性,不能保證業(yè)務(wù)結(jié)果中的每個(gè)步驟,在“任何時(shí)刻”都同時(shí)生效。
- 最終一致性,經(jīng)過一段時(shí)間以后,業(yè)務(wù)結(jié)果中的每個(gè)步驟都會(huì)最終生效。
可用性(Availability),reads and writes always succeed,按照原文翻譯是:任何時(shí)候,分布式系統(tǒng)的讀寫操作都是成功的。
也就是說,在規(guī)定時(shí)間內(nèi),分布式系統(tǒng)對接收到的每個(gè)用戶請求,都可以返回正常的業(yè)務(wù)結(jié)果。
分區(qū)容錯(cuò)性(Partition tolerance),the system continues to operate despite arbitrary message loss or failure of part of the system,這個(gè)說得比較繞一些。
我們可以這樣理解,當(dāng)分布式系統(tǒng)遇到網(wǎng)絡(luò)分區(qū)故障的時(shí)候,仍然能夠?qū)ν馓峁M足一致性或可用性的服務(wù)。
這里的網(wǎng)絡(luò)分區(qū)故障,指的是集群中各個(gè)節(jié)點(diǎn)的網(wǎng)絡(luò)相互不連通,被分成了幾個(gè)孤立的區(qū)域。
圖片
BASE定理
BASE 定理是對 CAP 定理中 AP 方案的延伸,旨在通過最終一致性的方式來替代 CAP 定理中的強(qiáng)一致性。
BASE 定理 = 基本可用(Basically Available)+ Soft state(軟狀態(tài))+ Eventually consistent(最終一致性)
- 基本可用,當(dāng)分布式系統(tǒng)出現(xiàn)不可預(yù)知故障的時(shí)候,允許損失部分可用性,保證其核心功能可用。
- 軟狀態(tài),允許分布式系統(tǒng)中的數(shù)據(jù)存在中間狀態(tài),且該中間狀態(tài)的存在不會(huì)影響系統(tǒng)的整體可用性。
- 最終一致性,經(jīng)過一段時(shí)間以后,分布式系統(tǒng)能夠達(dá)到業(yè)務(wù)邏輯一致性的狀態(tài)。
對于分布式事務(wù)來說,可以分為剛性事務(wù)和柔性事務(wù)兩種,其中剛性事務(wù)中的2PC、3PC滿足于 CAP 定理中 CP 的要求。
而柔性事務(wù)中的TCC、SAGA、本地消息表、事務(wù)消息和最大努力通知,則符合于 BASE 定理。
接下來我們再著重于分析一下,我們常用的一些中間件集群,它們都符合于CAP定理中的哪兩個(gè),為我們?nèi)粘9ぷ髦械募夹g(shù)選型提供一些參考。
MySQL主從架構(gòu)
MySQL主從復(fù)制屬于AP還是CP模型不能一概而論,因?yàn)槠渲С秩N方式:異步復(fù)制(默認(rèn))、半同步復(fù)制和全同步復(fù)制。
MySQL中的異步復(fù)制屬于AP模型。
主庫執(zhí)行寫操作并將該變更記錄到Binlog文件中,此時(shí)就會(huì)給客戶端返回結(jié)果,不需要等待從庫對主庫的日志事件進(jìn)行確認(rèn)。
圖片
當(dāng)異步復(fù)制方式出現(xiàn)網(wǎng)絡(luò)分區(qū)故障時(shí),主庫無法將變更的數(shù)據(jù)同步到從庫,就會(huì)產(chǎn)生主從庫數(shù)據(jù)不一致的情況。
以經(jīng)典的電商下單場景為例:
圖片
MySQL中的全同步復(fù)制屬于CP模型。
MySQL主庫執(zhí)行寫操作,并將該變更記錄到Binlog文件中,還需要等待所有從庫對主庫的日志事件進(jìn)行確認(rèn)后,才會(huì)給客戶端返回結(jié)果。
這里需要說明的是,只有在從庫的IO Thread將從主庫接收的Binlog文件寫入到本地的Relay Log中,才會(huì)對主庫的日志事件進(jìn)行確認(rèn)。
當(dāng)全同步復(fù)制方式出現(xiàn)網(wǎng)絡(luò)分區(qū)故障時(shí),主庫為了保證與從庫的數(shù)據(jù)一致性,將不再接受insert、update、delete等寫操作,直到故障恢復(fù)。
MySQL中的半同步復(fù)制屬于AP模型。
MySQL主庫執(zhí)行寫操作,并將該變更記錄到Binlog文件中,還需要等待至少一個(gè)從庫(可配置)對主庫的日志事件進(jìn)行確認(rèn)后,才會(huì)給客戶端返回結(jié)果。
也就是說,半同步復(fù)制不需要保證全部主從數(shù)據(jù)庫的數(shù)據(jù)一致性。
Redis Cluster
Redis Cluster的主從復(fù)制過程為:
Redis Cluster中的主節(jié)點(diǎn)每執(zhí)行一個(gè)寫操作,都會(huì)將該命令寫入到復(fù)制積壓緩沖區(qū)中,并更新自己的偏移量。
同時(shí),主節(jié)點(diǎn)通過 TCP 連接將寫命令發(fā)送給從節(jié)點(diǎn),從節(jié)點(diǎn)執(zhí)行命令后更新自己的偏移量,保持與主節(jié)點(diǎn)一致。
需要注意的是,主節(jié)點(diǎn)發(fā)送命令后無需等待從節(jié)點(diǎn)確認(rèn),而繼續(xù)執(zhí)行新的操作,可能會(huì)存在 “主節(jié)點(diǎn)宕機(jī)時(shí),部分命令未同步到從節(jié)點(diǎn)” 的數(shù)據(jù)丟失風(fēng)險(xiǎn)。
圖片
復(fù)制偏移量
主節(jié)點(diǎn)和從節(jié)點(diǎn)各自維護(hù)一個(gè)偏移量,記錄已處理的字節(jié)數(shù)(主節(jié)點(diǎn)發(fā)送的字節(jié)數(shù)、從節(jié)點(diǎn)接收的字節(jié)數(shù)),當(dāng)兩者偏移量相等時(shí),說明數(shù)據(jù)完全同步。
復(fù)制積壓緩沖區(qū)
主節(jié)點(diǎn)內(nèi)部維護(hù)一個(gè)固定大小的環(huán)形緩沖區(qū)(默認(rèn) 1MB),用于緩存最近發(fā)送的寫命令。
當(dāng)從節(jié)點(diǎn)因網(wǎng)絡(luò)波動(dòng)短暫斷線后重新連接時(shí),會(huì)向主節(jié)點(diǎn)發(fā)送自己的偏移量,主節(jié)點(diǎn)只需將緩沖區(qū)中 “從節(jié)點(diǎn)缺失的命令”(偏移量之后的命令)發(fā)送給從節(jié)點(diǎn),無需全量同步,大幅減少開銷。
由此可見,Redis Cluster也屬于AP模型,否則就不需要復(fù)制偏移量和復(fù)制積壓緩沖區(qū)來保證最終一致性了。
ElasticSearch集群
ElasticSearch集群寫操作的實(shí)現(xiàn)原理為,客戶端請求通過協(xié)調(diào)節(jié)點(diǎn)路由到主分片,主分片處理完成后同步至副本分片。
而寫操作一致性的設(shè)定,是通過consistency參數(shù)實(shí)現(xiàn)的,包括:one(僅主分片確認(rèn))、all(全部分片確認(rèn))和 quorum(大多數(shù)分片確認(rèn),默認(rèn)值)。
quorum的計(jì)算公式為:int((primary_shards + number_of_replicas) / 2) + 1,如果ElasticSearch集群有三個(gè)主分片和一個(gè)副本,那至少有三個(gè)分片可用才能執(zhí)行寫入操作。
由此可見,ElasticSearch集群屬于CP模式還是AP模式,需要看具體設(shè)定,如果consistency參數(shù)設(shè)置為all是CP模式,否則是AP模式。


































