偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

神一樣的CAP理論被應(yīng)用在何方?

原創(chuàng)
開(kāi)發(fā) 架構(gòu)
對(duì)于開(kāi)發(fā)或設(shè)計(jì)分布式系統(tǒng)的架構(gòu)師工程師來(lái)說(shuō),CAP 是必須要掌握的理論。

【51CTO.com原創(chuàng)稿件】對(duì)于開(kāi)發(fā)或設(shè)計(jì)分布式系統(tǒng)的架構(gòu)師工程師來(lái)說(shuō),CAP 是必須要掌握的理論。

?[[275972]]?

圖片來(lái)自 Pexels

But:這個(gè)文章的重點(diǎn)并不是討論 CAP 理論和細(xì)節(jié),重點(diǎn)是說(shuō)說(shuō) CAP 在微服務(wù)中的開(kāi)發(fā)怎么起到一個(gè)指引作用,會(huì)通過(guò)幾個(gè)微服務(wù)開(kāi)發(fā)的例子說(shuō)明,盡量的去貼近開(kāi)發(fā)。

CAP 定理又被稱(chēng)為布魯爾定理,是加州大學(xué)計(jì)算機(jī)科學(xué)家埃里克·布魯爾提出來(lái)的猜想,后來(lái)被證明成為分布式計(jì)算領(lǐng)域公認(rèn)的定理。

不過(guò)布魯爾在出來(lái) CAP 的時(shí)候并沒(méi)有對(duì) CAP 三者(Consistency,Availability,Partition tolerance)進(jìn)行詳細(xì)的定義,所以在網(wǎng)上也出現(xiàn)了不少對(duì) CAP 不同解讀的聲音。

CAP 定理

CAP 定理在發(fā)展中存在過(guò)兩個(gè)版本,我們以第二個(gè)版本為準(zhǔn):

在一個(gè)分布式系統(tǒng)中(指互相連接并共享數(shù)據(jù)的節(jié)點(diǎn)集合)中,當(dāng)涉及到讀寫(xiě)操作時(shí),只能保證一致性(Consistence)、可用性(Availability)、分區(qū)容錯(cuò)性(Partition Tolerance)三者中的兩個(gè),另外一個(gè)必須被犧牲。

??

這個(gè)版本的 CAP 理論在探討分布式系統(tǒng),更加強(qiáng)調(diào)兩點(diǎn)是互聯(lián)和共享數(shù)據(jù),其實(shí)也是理清楚了第一個(gè)版本中三選二的一些缺陷。

分布式系統(tǒng)不一定都存在互聯(lián)和共享數(shù)據(jù),例如 Memcached 集群相互間就沒(méi)有存在連接和共享數(shù)據(jù)。

所以 Memcached 集群這類(lèi)的分布式系統(tǒng)并不在 CAP 理論討論的范圍,而像 MySQL 集群就是互聯(lián)和數(shù)據(jù)共享復(fù)制,因此 MySQL 集群是屬于 CAP 理論討論的對(duì)象。

一致性(Consistency)

一致性意思就是寫(xiě)操作之后進(jìn)行讀操作無(wú)論在哪個(gè)節(jié)點(diǎn)都需要返回寫(xiě)操作的值。

可用性(Availability)

非故障的節(jié)點(diǎn)在合理的時(shí)間內(nèi)返回合理的響應(yīng)。

分區(qū)容錯(cuò)性(Partition Tolerance)

當(dāng)網(wǎng)絡(luò)出現(xiàn)分區(qū)后,系統(tǒng)依然能夠繼續(xù)旅行社職責(zé)。

在分布式的環(huán)境下,網(wǎng)絡(luò)無(wú)法做到 100% 可靠,有可能出現(xiàn)故障,因此分區(qū)是一個(gè)必須的選項(xiàng)。

如果選擇了 CA 而放棄了 P,若發(fā)生分區(qū)現(xiàn)象,為了保證 C,系統(tǒng)需要禁止寫(xiě)入,此時(shí)就與 A 發(fā)生沖突;如果是為了保證 A,則會(huì)出現(xiàn)正常的分區(qū)可以寫(xiě)入數(shù)據(jù),有故障的分區(qū)不能寫(xiě)入數(shù)據(jù),則與 C 就沖突了。

因此分布式系統(tǒng)理論上不可能選擇 CA 架構(gòu),而必須選擇 CP 或 AP 架構(gòu)。

分布式事務(wù) BASE 理論

BASE 理論是對(duì) CAP 的延伸和補(bǔ)充,是對(duì) CAP 中的 AP 方案的一個(gè)補(bǔ)充,即使在選擇 AP 方案的情況下,如何更好的最終達(dá)到 C。

BASE 是基本可用,柔性狀態(tài),最終一致性三個(gè)短語(yǔ)的縮寫(xiě),核心的思想是即使無(wú)法做到強(qiáng)一致性,但應(yīng)用可以采用適合的方式達(dá)到最終一致性。

CAP 在服務(wù)中實(shí)際的應(yīng)用例子

?[[275974]]?

理解貌似講多了,項(xiàng)目的 CAP 可以參考下李運(yùn)華的《從零開(kāi)始學(xué)架構(gòu)》的書(shū)里面的 21,22 章,比較詳細(xì)的描繪了 CAP 的理論細(xì)節(jié)和 CAP 的版本演化過(guò)程。

這里著重講解的是神一樣的 CAP 在我們的微服務(wù)中怎么去指導(dǎo)和應(yīng)用起來(lái),大概會(huì)舉幾個(gè)平時(shí)常見(jiàn)的例子。

??

服務(wù)注冊(cè)中心,是選擇 CA 還是選擇 CP?

服務(wù)注冊(cè)中心解決的問(wèn)題

在討論 CAP 之前先明確下服務(wù)注冊(cè)中心主要是解決什么問(wèn)題:


  • 服務(wù)注冊(cè):實(shí)例將自身服務(wù)信息注冊(cè)到注冊(cè)中心,這部分信息包括服務(wù)的主機(jī) IP 和服務(wù)的 Port,以及暴露服務(wù)自身狀態(tài)和訪問(wèn)協(xié)議信息等。
  • 服務(wù)發(fā)現(xiàn):實(shí)例請(qǐng)求注冊(cè)中心所依賴(lài)的服務(wù)信息,服務(wù)實(shí)例通過(guò)注冊(cè)中心,獲取到注冊(cè)到其中的服務(wù)實(shí)例的信息,通過(guò)這些信息去請(qǐng)求它們提供的服務(wù)。

??

目前作為注冊(cè)中心的一些組件大致有:


  • Dubbo 的 Zookeeper
  • Spring Cloud 的 Eureka,Consul
  • RocketMQ 的 nameServer
  • HDFS 的 nameNode

目前微服務(wù)主流是 Dubbo 和 Spring Cloud,使用最多是 Zookeeper 和 Eureka,我們就來(lái)看看應(yīng)該根據(jù) CAP 理論怎么去選擇注冊(cè)中心。(Spring Cloud 也可以用 ZK,不過(guò)不是主流不討論)

Zookeeper 選擇 CP

Zookeeper 保證 CP,即任何時(shí)刻對(duì) Zookeeper 的訪問(wèn)請(qǐng)求能得到一致性的數(shù)據(jù)結(jié)果,同時(shí)系統(tǒng)對(duì)網(wǎng)絡(luò)分割具備容錯(cuò)性,但是它不能保證每次服務(wù)的可用性。

從實(shí)際情況來(lái)分析,在使用 Zookeeper 獲取服務(wù)列表時(shí),如果 ZK 正在選舉或者 ZK 集群中半數(shù)以上的機(jī)器不可用,那么將無(wú)法獲取數(shù)據(jù)。所以說(shuō),ZK 不能保證服務(wù)可用性。

Eureka 選擇 AP

Eureka 保證 AP,Eureka 在設(shè)計(jì)時(shí)優(yōu)先保證可用性,每一個(gè)節(jié)點(diǎn)都是平等的。

一部分節(jié)點(diǎn)掛掉不會(huì)影響到正常節(jié)點(diǎn)的工作,不會(huì)出現(xiàn)類(lèi)似 ZK 的選舉 Leader 的過(guò)程,客戶(hù)端發(fā)現(xiàn)向某個(gè)節(jié)點(diǎn)注冊(cè)或連接失敗,會(huì)自動(dòng)切換到其他的節(jié)點(diǎn)。

只要有一臺(tái) Eureka 存在,就可以保證整個(gè)服務(wù)處在可用狀態(tài),只不過(guò)有可能這個(gè)服務(wù)上的信息并不是最新的信息。

ZK 和 Eureka 的數(shù)據(jù)一致性問(wèn)題

先要明確一點(diǎn),Eureka 的創(chuàng)建初心就是為一個(gè)注冊(cè)中心,但是 ZK 更多是作為分布式協(xié)調(diào)服務(wù)的存在。

只不過(guò)因?yàn)樗奶匦员?Dubbo 賦予了注冊(cè)中心,它的職責(zé)更多是保證數(shù)據(jù)(配置數(shù)據(jù),狀態(tài)數(shù)據(jù))在管轄下的所有服務(wù)之間保持一致。

所以這個(gè)就不難理解為何 ZK 被設(shè)計(jì)成 CP 而不是 AP,ZK 最核心的算法 ZAB,就是為了解決分布式系統(tǒng)下數(shù)據(jù)在多個(gè)服務(wù)之間一致同步的問(wèn)題。

更深層的原因,ZK 是按照 CP 原則構(gòu)建,也就是說(shuō)它必須保持每一個(gè)節(jié)點(diǎn)的數(shù)據(jù)都保持一致。

如果 ZK 下節(jié)點(diǎn)斷開(kāi)或者集群中出現(xiàn)網(wǎng)絡(luò)分割(例如交換機(jī)的子網(wǎng)間不能互訪),那么 ZK 會(huì)將它們從自己的管理范圍中剔除,外界不能訪問(wèn)這些節(jié)點(diǎn),即使這些節(jié)點(diǎn)是健康的可以提供正常的服務(wù),所以導(dǎo)致這些節(jié)點(diǎn)請(qǐng)求都會(huì)丟失。

而 Eureka 則完全沒(méi)有這方面的顧慮,它的節(jié)點(diǎn)都是相對(duì)獨(dú)立,不需要考慮數(shù)據(jù)一致性的問(wèn)題,這個(gè)應(yīng)該是 Eureka 的誕生就是為了注冊(cè)中心而設(shè)計(jì)。

相對(duì) ZK 來(lái)說(shuō)剔除了 Leader 節(jié)點(diǎn)選取和事務(wù)日志機(jī)制,這樣更有利于維護(hù)和保證 Eureka 在運(yùn)行的健壯性。

??

再來(lái)看看,數(shù)據(jù)不一致性在注冊(cè)服務(wù)中會(huì)給 Eureka 帶來(lái)什么問(wèn)題,無(wú)非就是某一個(gè)節(jié)點(diǎn)被注冊(cè)的服務(wù)多,某個(gè)節(jié)點(diǎn)注冊(cè)的服務(wù)少,在某一個(gè)瞬間可能導(dǎo)致某些 IP 節(jié)點(diǎn)被調(diào)用數(shù)多,某些 IP 節(jié)點(diǎn)調(diào)用數(shù)少的問(wèn)題。

也有可能存在一些本應(yīng)該被刪除而沒(méi)被刪除的臟數(shù)據(jù)。

??

服務(wù)注冊(cè)應(yīng)該選擇 AP 還是 CP

對(duì)于服務(wù)注冊(cè)來(lái)說(shuō),針對(duì)同一個(gè)服務(wù),即使注冊(cè)中心的不同節(jié)點(diǎn)保存的服務(wù)注冊(cè)信息不相同,也并不會(huì)造成災(zāi)難性的后果。

對(duì)于服務(wù)消費(fèi)者來(lái)說(shuō),能消費(fèi)才是最重要的,就算拿到的數(shù)據(jù)不是最新的數(shù)據(jù),消費(fèi)者本身也可以進(jìn)行嘗試失敗重試??偙葹榱俗非髷?shù)據(jù)的一致性而獲取不到實(shí)例信息整個(gè)服務(wù)不可用要好。

所以,對(duì)于服務(wù)注冊(cè)來(lái)說(shuō),可用性比數(shù)據(jù)一致性更加的重要,選擇 AP。

分布式鎖,是選擇 CA 還是選擇 CP?

這里實(shí)現(xiàn)分布式鎖的方式選取了三種:


  • 基于數(shù)據(jù)庫(kù)實(shí)現(xiàn)分布式鎖
  • 基于 Redis 實(shí)現(xiàn)分布式鎖
  • 基于 Zookeeper 實(shí)現(xiàn)分布式鎖

基于數(shù)據(jù)庫(kù)實(shí)現(xiàn)分布式鎖

構(gòu)建表結(jié)構(gòu):

??

利用表的 UNIQUE KEY idx_lock(method_lock)作為唯一主鍵,當(dāng)進(jìn)行上鎖時(shí)進(jìn)行 Insert 動(dòng)作,數(shù)據(jù)庫(kù)成功錄入則以為上鎖成功,當(dāng)數(shù)據(jù)庫(kù)報(bào)出 Duplicate entry 則表示無(wú)法獲取該鎖。

??

不過(guò)這種方式對(duì)于單主卻無(wú)法自動(dòng)切換主從的 MySQL 來(lái)說(shuō),基本就無(wú)法實(shí)現(xiàn) P 分區(qū)容錯(cuò)性(MySQL 自動(dòng)主從切換在目前并沒(méi)有十分完美的解決方案)。

可以說(shuō)這種方式強(qiáng)依賴(lài)于數(shù)據(jù)庫(kù)的可用性,數(shù)據(jù)庫(kù)寫(xiě)操作是一個(gè)單點(diǎn),一旦數(shù)據(jù)庫(kù)掛掉,就導(dǎo)致鎖的不可用。這種方式基本不在 CAP 的一個(gè)討論范圍。

基于 Redis 實(shí)現(xiàn)分布式鎖

Redis 單線程串行處理天然就是解決串行化問(wèn)題,用來(lái)解決分布式鎖是再適合不過(guò)。

實(shí)現(xiàn)方式:

setnx key value Expire_time 獲取到鎖 返回 1 , 獲取失敗 返回 0 

為了解決數(shù)據(jù)庫(kù)鎖的無(wú)主從切換的問(wèn)題,可以選擇 Redis 集群,或者是 Sentinel 哨兵模式,實(shí)現(xiàn)主從故障轉(zhuǎn)移,當(dāng) Master 節(jié)點(diǎn)出現(xiàn)故障,哨兵會(huì)從 Slave 中選取節(jié)點(diǎn),重新變成新的 Master 節(jié)點(diǎn)。

??

哨兵模式故障轉(zhuǎn)移是由 Sentinel 集群進(jìn)行監(jiān)控判斷,當(dāng) Maser 出現(xiàn)異常即復(fù)制中止,重新推選新 Slave 成為 Master,Sentinel 在重新進(jìn)行選舉并不在意主從數(shù)據(jù)是否復(fù)制完畢具備一致性。

所以 Redis 的復(fù)制模式是屬于 AP 的模式。保證可用性,在主從復(fù)制中“主”有數(shù)據(jù),但是可能“從”還沒(méi)有數(shù)據(jù)。

這個(gè)時(shí)候,一旦主掛掉或者網(wǎng)絡(luò)抖動(dòng)等各種原因,可能會(huì)切換到“從”節(jié)點(diǎn),這個(gè)時(shí)候可能會(huì)導(dǎo)致兩個(gè)業(yè)務(wù)線程同時(shí)獲取得兩把鎖。

??

這個(gè)過(guò)程如下:


  • 業(yè)務(wù)線程 -1 向主節(jié)點(diǎn)請(qǐng)求鎖
  • 業(yè)務(wù)線程 -1 獲取鎖
  • 業(yè)務(wù)線程 -1 獲取到鎖并開(kāi)始執(zhí)行業(yè)務(wù)
  • 這個(gè)時(shí)候 Redis 剛生成的鎖在主從之間還未進(jìn)行同步
  • Redis 這時(shí)候主節(jié)點(diǎn)掛掉了
  • Redis 的從節(jié)點(diǎn)升級(jí)為主節(jié)點(diǎn)
  • 業(yè)務(wù)線程 -2 想新的主節(jié)點(diǎn)請(qǐng)求鎖
  • 業(yè)務(wù)線程 -2 獲取到新的主節(jié)點(diǎn)返回的鎖
  • 業(yè)務(wù)線程 -2 獲取到鎖開(kāi)始執(zhí)行業(yè)務(wù)
  • 這個(gè)時(shí)候業(yè)務(wù)線程 -1 和業(yè)務(wù)線程 -2 同時(shí)在執(zhí)行任務(wù)

上述的問(wèn)題其實(shí)并不是 Redis 的缺陷,只是 Redis 采用了 AP 模型,它本身無(wú)法確保我們對(duì)一致性的要求。

Redis 官方推薦 Redlock 算法來(lái)保證,問(wèn)題是 Redlock 至少需要三個(gè) Redis 主從實(shí)例來(lái)實(shí)現(xiàn),維護(hù)成本比較高。

相當(dāng)于 Redlock 使用三個(gè) Redis 集群實(shí)現(xiàn)了自己的另一套一致性算法,比較繁瑣,在業(yè)界也使用得比較少。

能不能使用 Redis 作為分布式鎖?這個(gè)本身就不是 Redis 的問(wèn)題,還是取決于業(yè)務(wù)場(chǎng)景。

我們先要自己確認(rèn)我們的場(chǎng)景是適合 AP 還是 CP , 如果在社交發(fā)帖等場(chǎng)景下,我們并沒(méi)有非常強(qiáng)的事務(wù)一致性問(wèn)題,Redis 提供給我們高性能的 AP 模型是非常適合的。

但如果是交易類(lèi)型,對(duì)數(shù)據(jù)一致性非常敏感的場(chǎng)景,我們可能要尋找一種更加適合的 CP 模型。

基于 Zookeeper 實(shí)現(xiàn)分布式鎖

剛剛也分析過(guò),Redis 其實(shí)無(wú)法確保數(shù)據(jù)的一致性,先來(lái)看 Zookeeper 是否適合作為我們需要的分布式鎖。

首先 ZK 的模式是 CP 模型,也就是說(shuō),當(dāng) ZK 鎖提供給我們進(jìn)行訪問(wèn)的時(shí)候,在 ZK 集群中能確保這把鎖在 ZK 的每一個(gè)節(jié)點(diǎn)都存在。

??

這個(gè)實(shí)際上是 ZK 的 Leader 通過(guò)二階段提交寫(xiě)請(qǐng)求來(lái)保證的,這個(gè)也是 ZK 的集群規(guī)模大了的一個(gè)瓶頸點(diǎn)。

①ZK 鎖實(shí)現(xiàn)的原理

說(shuō) ZK 的鎖問(wèn)題之前先看看 Zookeeper 中幾個(gè)特性,這幾個(gè)特性構(gòu)建了 ZK 的一把分布式鎖。

ZK 的特性如下:


  • 有序節(jié)點(diǎn):當(dāng)在一個(gè)父目錄下如 /lock 下創(chuàng)建 有序節(jié)點(diǎn),節(jié)點(diǎn)會(huì)按照嚴(yán)格的先后順序創(chuàng)建出自節(jié)點(diǎn) lock000001,lock000002,lock0000003,以此類(lèi)推,有序節(jié)點(diǎn)能?chē)?yán)格保證各個(gè)自節(jié)點(diǎn)按照排序命名生成。
  • 臨時(shí)節(jié)點(diǎn):客戶(hù)端建立了一個(gè)臨時(shí)節(jié)點(diǎn),在客戶(hù)端的會(huì)話結(jié)束或會(huì)話超時(shí),Zookepper 會(huì)自動(dòng)刪除該節(jié)點(diǎn) ID。
  • 事件監(jiān)聽(tīng):在讀取數(shù)據(jù)時(shí),我們可以對(duì)節(jié)點(diǎn)設(shè)置監(jiān)聽(tīng),當(dāng)節(jié)點(diǎn)的數(shù)據(jù)發(fā)生變化(1 節(jié)點(diǎn)創(chuàng)建 2 節(jié)點(diǎn)刪除 3 節(jié)點(diǎn)數(shù)據(jù)變成 4 自節(jié)點(diǎn)變成)時(shí),Zookeeper 會(huì)通知客戶(hù)端。

??

結(jié)合這幾個(gè)特點(diǎn),來(lái)看下 ZK 是怎么組合分布式鎖:


  • 業(yè)務(wù)線程 -1,業(yè)務(wù)線程 -2 分別向 ZK 的 /lock 目錄下,申請(qǐng)創(chuàng)建有序的臨時(shí)節(jié)點(diǎn)。
  • 業(yè)務(wù)線程 -1 搶到 /lock0001 的文件,也就是在整個(gè)目錄下最小序的節(jié)點(diǎn),也就是線程 -1 獲取到了鎖。
  • 業(yè)務(wù)線程 -2 只能搶到 /lock0002 的文件,并不是最小序的節(jié)點(diǎn),線程 2 未能獲取鎖。
  • 業(yè)務(wù)線程 -1 與 lock0001 建立了連接,并維持了心跳,維持的心跳也就是這把鎖的租期。
  • 當(dāng)業(yè)務(wù)線程 -1 完成了業(yè)務(wù),將釋放掉與 ZK 的連接,也就是釋放了這把鎖。

②ZK 分布式鎖的代碼實(shí)現(xiàn)

ZK 官方提供的客戶(hù)端并不支持分布式鎖的直接實(shí)現(xiàn),我們需要自己寫(xiě)代碼去利用 ZK 的這幾個(gè)特性去進(jìn)行實(shí)現(xiàn)。

??

究竟該用 CP 還是 AP 的分布式鎖

首先得了解清楚我們使用分布式鎖的場(chǎng)景,為何使用分布式鎖,用它來(lái)幫我們解決什么問(wèn)題,先聊場(chǎng)景后聊分布式鎖的技術(shù)選型。

無(wú)論是 Redis,ZK,例如 Redis 的 AP 模型會(huì)限制很多使用場(chǎng)景,但它卻擁有了幾者中最高的性能。

Zookeeper 的分布式鎖要比 Redis 可靠很多,但他繁瑣的實(shí)現(xiàn)機(jī)制導(dǎo)致了它的性能不如 Redis,而且 ZK 會(huì)隨著集群的擴(kuò)大而性能更加下降。

簡(jiǎn)單來(lái)說(shuō),先了解業(yè)務(wù)場(chǎng)景,后進(jìn)行技術(shù)選型。

分布式事務(wù),是怎么從 ACID 解脫,投身 CAP/BASE

如果說(shuō)到事務(wù),ACID 是傳統(tǒng)數(shù)據(jù)庫(kù)常用的設(shè)計(jì)理念,追求強(qiáng)一致性模型,關(guān)系數(shù)據(jù)庫(kù)的 ACID 模型擁有高一致性+可用性,所以很難進(jìn)行分區(qū)。

在微服務(wù)中 ACID 已經(jīng)是無(wú)法支持,我們還是回到 CAP 去尋求解決方案,不過(guò)根據(jù)上面的討論,CAP 定理中,要么只能 CP,要么只能 AP。

如果我們追求數(shù)據(jù)的一致性而忽略可用性這個(gè)在微服務(wù)中肯定是行不通的,如果我們追求可用性而忽略一致性,那么在一些重要的數(shù)據(jù)(例如支付,金額)肯定出現(xiàn)漏洞百出,這個(gè)也是無(wú)法接受。所以我們既要一致性,也要可用性。

??

都要是無(wú)法實(shí)現(xiàn)的,但我們能不能在一致性上作出一些妥協(xié),不追求強(qiáng)一致性,轉(zhuǎn)而追求最終一致性,所以引入 BASE 理論。

在分布式事務(wù)中,BASE 最重要是為 CAP 提出了最終一致性的解決方案,BASE 強(qiáng)調(diào)犧牲高一致性,從而獲取可用性,數(shù)據(jù)允許在一段時(shí)間內(nèi)不一致,只要保證最終一致性就可以了。

實(shí)現(xiàn)最終一致性

弱一致性:系統(tǒng)不能保證后續(xù)訪問(wèn)返回更新的值。需要在一些條件滿(mǎn)足之后,更新的值才能返回。

從更新操作開(kāi)始,到系統(tǒng)保證任何觀察者總是看到更新的值的這期間被稱(chēng)為不一致窗口。

最終一致性:這是弱一致性的特殊形式;存儲(chǔ)系統(tǒng)保證如果沒(méi)有對(duì)某個(gè)對(duì)象的新更新操作,最終所有的訪問(wèn)將返回這個(gè)對(duì)象的最后更新的值。

BASE 模型

BASE 模型是傳統(tǒng) ACID 模型的反面,不同于 ACID,BASE 強(qiáng)調(diào)犧牲高一致性,從而獲得可用性,數(shù)據(jù)允許在一段時(shí)間內(nèi)的不一致,只要保證最終一致就可以了。

BASE 模型反 ACID 模型,完全不同 ACID 模型,犧牲高一致性,獲得可用性或可靠性:Basically Available 基本可用。

支持分區(qū)失敗(e.g. sharding碎片劃分?jǐn)?shù)據(jù)庫(kù))Soft state 軟狀態(tài),狀態(tài)可以有一段時(shí)間不同步,異步。

Eventually consistent 最終一致,最終數(shù)據(jù)是一致的就可以了,而不是時(shí)時(shí)一致。

分布式事務(wù)

在分布式系統(tǒng)中,要實(shí)現(xiàn)分布式事務(wù),無(wú)外乎幾種解決方案。方案各有不同,不過(guò)其實(shí)都是遵循 BASE 理論,是最終一致性模型:


  • 兩階段提交(2PC)
  • 補(bǔ)償事務(wù)(TCC)
  • 本地消息表
  • MQ 事務(wù)消息

①兩階段提交(2PC)

還有一個(gè)數(shù)據(jù)庫(kù)的 XA 事務(wù),不過(guò)目前在真正的互聯(lián)網(wǎng)中實(shí)際的應(yīng)用基本很少,兩階段提交就是使用 XA 原理。

??

在 XA 協(xié)議中分為兩階段:


  • 事務(wù)管理器要求每個(gè)涉及到事務(wù)的數(shù)據(jù)庫(kù)預(yù)提交(Precommit)此操作,并反映是否可以提交。
  • 事務(wù)協(xié)調(diào)器要求每個(gè)數(shù)據(jù)庫(kù)提交數(shù)據(jù),或者回滾數(shù)據(jù)。

說(shuō)一下,為何在互聯(lián)網(wǎng)的系統(tǒng)中沒(méi)被改造過(guò)的兩階段提交基本很少被業(yè)界應(yīng)用,最大的缺點(diǎn)就是同步阻塞問(wèn)題。

在資源準(zhǔn)備就緒之后,資源管理器中的資源就一直處于阻塞,直到提交完成之后,才進(jìn)行資源釋放。

這個(gè)在互聯(lián)網(wǎng)高并發(fā)大數(shù)據(jù)的今天,兩階段的提交是不能滿(mǎn)足現(xiàn)在互聯(lián)網(wǎng)的發(fā)展。

還有就是兩階段提交協(xié)議雖然為分布式數(shù)據(jù)強(qiáng)一致性所設(shè)計(jì),但仍然存在數(shù)據(jù)不一致性的可能。

例如:在第二階段中,假設(shè)協(xié)調(diào)者發(fā)出了事務(wù) Commit 的通知,但是因?yàn)榫W(wǎng)絡(luò)問(wèn)題該通知僅被一部分參與者所收到并執(zhí)行了 Commit 操作,其余的參與者則因?yàn)闆](méi)有收到通知一直處于阻塞狀態(tài),這時(shí)候就產(chǎn)生了數(shù)據(jù)的不一致性。

②補(bǔ)償事務(wù)(TCC)

TCC 是服務(wù)化的兩階段編程模型,每個(gè)業(yè)務(wù)服務(wù)都必須實(shí)現(xiàn) Try,Confirm,Cancel 三個(gè)方法,這三個(gè)方式可以對(duì)應(yīng)到 SQL 事務(wù)中 Lock,Commit,Rollback。

??

相比兩階段提交,TCC 解決了幾個(gè)問(wèn)題:同步阻塞,引入了超時(shí)機(jī)制,超時(shí)后進(jìn)行補(bǔ)償,并不會(huì)像兩階段提交鎖定了整個(gè)資源,將資源轉(zhuǎn)換為業(yè)務(wù)邏輯形式,粒度變小。

因?yàn)橛辛搜a(bǔ)償機(jī)制,可以由業(yè)務(wù)活動(dòng)管理器進(jìn)行控制,保證數(shù)據(jù)一致性。

Try 階段:Try 只是一個(gè)初步的操作,進(jìn)行初步的確認(rèn),它的主要職責(zé)是完成所有業(yè)務(wù)的檢查,預(yù)留業(yè)務(wù)資源。

Confirm 階段:Confirm 是在 Try 階段檢查執(zhí)行完畢后,繼續(xù)執(zhí)行的確認(rèn)操作,必須滿(mǎn)足冪等性操作,如果 Confirm 中執(zhí)行失敗,會(huì)有事務(wù)協(xié)調(diào)器觸發(fā)不斷的執(zhí)行,直到滿(mǎn)足為止。

Cancel 是取消執(zhí)行:在 Try 沒(méi)通過(guò)并釋放掉 Try 階段預(yù)留的資源,也必須滿(mǎn)足冪等性,跟 Confirm 一樣有可能被不斷執(zhí)行。

一個(gè)下訂單,生成訂單扣庫(kù)存的例子:

??

接下來(lái)看看,我們的下單扣減庫(kù)存的流程怎么加入 TCC:

??

在 Try 的時(shí)候,會(huì)讓庫(kù)存服務(wù)預(yù)留 N 個(gè)庫(kù)存給這個(gè)訂單使用,讓訂單服務(wù)產(chǎn)生一個(gè)“未確認(rèn)”訂單,同時(shí)產(chǎn)生這兩個(gè)預(yù)留的資源。

在 Confirm 的時(shí)候,會(huì)使用在 Try 預(yù)留的資源,在 TCC 事務(wù)機(jī)制中認(rèn)為,如果在 Try 階段能正常預(yù)留的資源,那么在 Confirm 一定能完整的提交。

??

在 Try 的時(shí)候,有任務(wù)一方為執(zhí)行失敗,則會(huì)執(zhí)行 Cancel 的接口操作,將在 Try 階段預(yù)留的資源進(jìn)行釋放。

這個(gè)并不是重點(diǎn)要論 TCC 事務(wù)是怎么實(shí)現(xiàn),重點(diǎn)還是討論分布式事務(wù)在 CAP+BASE 理論的應(yīng)用。

實(shí)現(xiàn)可以參考:

https://github.com/changmingxie/tcc-transaction 

③本地消息表

本地消息表這個(gè)方案最初是 eBay 提出的,eBay 的完整方案:

https://queue.acm.org/detail.cfm?id=1394128 

本地消息表這種實(shí)現(xiàn)方式應(yīng)該是業(yè)界使用最多的,其核心思想是將分布式事務(wù)拆分成本地事務(wù)進(jìn)行處理。

??

對(duì)于本地消息隊(duì)列來(lái)說(shuō),核心就是將大事務(wù)轉(zhuǎn)變?yōu)樾∈聞?wù),還是用上面下訂單扣庫(kù)存的例子說(shuō)明:


  • 當(dāng)我們?nèi)?chuàng)建訂單的時(shí)候,我們新增一個(gè)本地消息表,把創(chuàng)建訂單和扣減庫(kù)存寫(xiě)入到本地消息表,放在同一個(gè)事務(wù)(依靠數(shù)據(jù)庫(kù)本地事務(wù)保證一致性)。
  • 配置一個(gè)定時(shí)任務(wù)去輪詢(xún)這個(gè)本地事務(wù)表,掃描這個(gè)本地事務(wù)表,把沒(méi)有發(fā)送出去的消息,發(fā)送給庫(kù)存服務(wù),當(dāng)庫(kù)存服務(wù)收到消息后,會(huì)進(jìn)行減庫(kù)存,并寫(xiě)入服務(wù)器的事務(wù)表,更新事務(wù)表的狀態(tài)。
  • 庫(kù)存服務(wù)器通過(guò)定時(shí)任務(wù)或直接通知訂單服務(wù),訂單服務(wù)在本地消息表更新?tīng)顟B(tài)。

這里須注意的是,對(duì)于一些掃描發(fā)送未成功的任務(wù),會(huì)進(jìn)行重新發(fā)送,所以必須保證接口的冪等性。

本地消息隊(duì)列是 BASE 理論,是最終一致性模型,適用對(duì)一致性要求不高的情況。

④MQ 事務(wù)

RocketMQ 在 4.3 版本已經(jīng)正式宣布支持分布式事務(wù),在選擇 RokcetMQ 做分布式事務(wù)請(qǐng)務(wù)必選擇 4.3 以上的版本。

RocketMQ 中實(shí)現(xiàn)了分布式事務(wù),實(shí)際上是對(duì)本地消息表的一個(gè)封裝,將本地消息表移動(dòng)到了 MQ 內(nèi)部。

??

事務(wù)消息作為一種異步確保型事務(wù), 將兩個(gè)事務(wù)分支通過(guò) MQ 進(jìn)行異步解耦,RocketMQ 事務(wù)消息的設(shè)計(jì)流程同樣借鑒了兩階段提交理論。

整體交互流程如下圖所示:

???

MQ 事務(wù)是對(duì)本地消息表的一層封裝,將本地消息表移動(dòng)到了 MQ 內(nèi)部,所以也是基于 BASE 理論,是最終一致性模式,對(duì)強(qiáng)一致性要求不那么高的事務(wù)適用,同時(shí) MQ 事務(wù)將整個(gè)流程異步化了,也非常適合在高并發(fā)情況下使用。


RocketMQ 選擇同步/異步刷盤(pán),同步/異步復(fù)制,背后的 CP 和 AP 思考

雖然同步刷盤(pán)/異步刷盤(pán),同步/異步復(fù)制,并沒(méi)有對(duì) CAP 直接的應(yīng)用,但在配置的過(guò)程中也一樣涉及到可用性和一致性的考慮。

同步刷盤(pán)/異步刷盤(pán)

??

RocketMQ 的消息是可以做到持久化的,數(shù)據(jù)會(huì)持久化到磁盤(pán),RocketMQ 為了提高性能,盡可能保證磁盤(pán)的順序?qū)懭搿?/p>

消息在 Producer 寫(xiě)入 RocketMQ 的時(shí)候,有兩種寫(xiě)入磁盤(pán)方式:


  • 異步刷盤(pán):消息快速寫(xiě)入到內(nèi)存的 Pagecache,就立馬返回寫(xiě)成功狀態(tài),當(dāng)內(nèi)存的消息累計(jì)到一定程度的時(shí)候,會(huì)觸發(fā)統(tǒng)一的寫(xiě)磁盤(pán)操作。這種方式可以保證大吞吐量,但也存在著消息可能未存入磁盤(pán)丟失的風(fēng)險(xiǎn)。
  • 同步刷盤(pán):消息快速寫(xiě)入內(nèi)存的 Pagecahe,立刻通知刷盤(pán)線程進(jìn)行刷盤(pán),等待刷盤(pán)完成之后,喚醒等待的線程,返回消息寫(xiě)成功的狀態(tài)。

同步復(fù)制/異步復(fù)制

??

一個(gè) Broker 組有 Master 和 Slave,消息需要從 Master 復(fù)制到 Slave 上,所以有同步和異步兩種復(fù)制方式:


  • 同步復(fù)制:是等 Master 和 Slave 均寫(xiě)成功后才反饋給客戶(hù)端寫(xiě)成功狀態(tài)。
  • 異步復(fù)制:是只要 Master 寫(xiě)成功即可反饋給客戶(hù)端寫(xiě)成功狀態(tài)。

異步復(fù)制的優(yōu)點(diǎn)是可以提高響應(yīng)速度,但犧牲了一致性 ,一般實(shí)現(xiàn)該類(lèi)協(xié)議的算法需要增加額外的補(bǔ)償機(jī)制。

同步復(fù)制的優(yōu)點(diǎn)是可以保證一致性(一般通過(guò)兩階段提交協(xié)議),但是開(kāi)銷(xiāo)較大,可用性不好(參見(jiàn) CAP 定理),帶來(lái)了更多的沖突和死鎖等問(wèn)題。

值得一提的是 Lazy+Primary/Copy 的復(fù)制協(xié)議在實(shí)際生產(chǎn)環(huán)境中是非常實(shí)用的。

??

RocketMQ 的設(shè)置要結(jié)合業(yè)務(wù)場(chǎng)景,合理設(shè)置刷盤(pán)方式和主從復(fù)制方式,尤其是 SYNC_FLUSH 方式,由于頻繁的觸發(fā)寫(xiě)磁盤(pán)動(dòng)作,會(huì)明顯降低性能。

通常情況下,應(yīng)該把 Master 和 Slave 設(shè)置成 ASYNC_FLUSH 的刷盤(pán)方式,主從之間配置成 SYNC_MASTER 的復(fù)制方式,這樣即使有一臺(tái)機(jī)器出故障,仍然可以保證數(shù)據(jù)不丟。

總結(jié)

在微服務(wù)的構(gòu)建中,永遠(yuǎn)都逃離不了 CAP 理論,因?yàn)榫W(wǎng)絡(luò)永遠(yuǎn)不穩(wěn)定,硬件總會(huì)老化,軟件可能出現(xiàn) Bug,所以分區(qū)容錯(cuò)性在微服務(wù)中是躲不過(guò)的命題。

可以這么說(shuō),只要是分布式,只要是集群都面臨著 AP 或者 CP 的選擇,但你很貪心的時(shí)候,既要一致性又要可用性,那只能對(duì)一致性作出一點(diǎn)妥協(xié),也就是引入了 BASE 理論,在業(yè)務(wù)允許的情況下實(shí)現(xiàn)最終一致性。

?[[275979]]?

究竟是選 CA 還是選 CP,真的在于對(duì)業(yè)務(wù)的了解,例如金錢(qián),庫(kù)存相關(guān)會(huì)優(yōu)先考慮 CP 模型,例如社區(qū)發(fā)帖相關(guān)可以?xún)?yōu)先選擇 AP 模型,這個(gè)說(shuō)白了基于對(duì)業(yè)務(wù)的了解是一個(gè)選擇和妥協(xié)的過(guò)程。

作者:陳于喆

簡(jiǎn)介:十余年的開(kāi)發(fā)和架構(gòu)經(jīng)驗(yàn),國(guó)內(nèi)較早一批微服務(wù)開(kāi)發(fā)實(shí)施者。曾任職國(guó)內(nèi)互聯(lián)網(wǎng)公司網(wǎng)易和唯品會(huì)高級(jí)研發(fā)工程師,后在創(chuàng)業(yè)公司擔(dān)任技術(shù)總監(jiān)/架構(gòu)師,目前在洋蔥集團(tuán)任職技術(shù)研發(fā)副總監(jiān)。

???

【51CTO原創(chuàng)稿件,合作站點(diǎn)轉(zhuǎn)載請(qǐng)注明原文作者和出處為51CTO.com】


責(zé)任編輯:武曉燕 來(lái)源: 51CTO技術(shù)棧
相關(guān)推薦

2009-12-25 15:11:08

FTTH應(yīng)用

2020-02-28 15:49:26

2021-04-22 22:29:40

Python開(kāi)發(fā)算法

2021-10-06 17:11:25

區(qū)塊鏈醫(yī)療應(yīng)用

2012-07-30 09:48:09

HTML5

2012-12-27 13:52:48

Android開(kāi)發(fā)判斷

2022-07-04 14:35:01

區(qū)塊鏈醫(yī)療供應(yīng)鏈

2023-04-11 07:46:11

平臺(tái)arthas線診斷

2022-03-29 14:46:03

元宇宙工業(yè)元宇宙物聯(lián)網(wǎng)

2019-11-15 14:53:49

大數(shù)據(jù)平臺(tái)智慧城市城市大數(shù)據(jù)

2013-05-23 14:20:50

PoE以太網(wǎng)IP終端地址

2020-12-14 18:02:25

區(qū)塊鏈人民幣技術(shù)

2023-01-03 14:54:37

技術(shù)管理

2022-11-30 08:53:51

CAP定理計(jì)算機(jī)

2018-05-29 00:00:32

物聯(lián)網(wǎng)物聯(lián)網(wǎng)應(yīng)用IOT

2022-03-03 21:45:58

大數(shù)據(jù)大數(shù)據(jù)技術(shù)

2013-03-11 10:02:42

2021-06-15 14:04:01

人工智能應(yīng)用人工智能AI

2021-03-29 12:45:24

微軟Edge瀏覽器

2014-07-11 10:10:58

SAPWindows Azu公有云
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)