常见分布式理论(CAP、BASE)和一致性协议(Gosssip协议、Raft一致性算法)
一、CAP理論與BASE理論:
1、什么是 CAP 理論:
-
C:Consistency 一致性:指強(qiáng)一致性,分布式系統(tǒng)中的所有節(jié)點(diǎn)在同一時(shí)刻具有同樣的值、都是最新的數(shù)據(jù)副本,一致性保證了不管向哪臺(tái)服務(wù)器寫(xiě)入數(shù)據(jù),其他的服務(wù)器能實(shí)時(shí)同步數(shù)據(jù)
-
A:Availability 可用性:部分結(jié)點(diǎn)宕機(jī)不影響整個(gè)集群對(duì)外提供服務(wù),每次向未故障的節(jié)點(diǎn)發(fā)送請(qǐng)求,服務(wù)節(jié)點(diǎn)總能保證在有限的時(shí)間內(nèi)處理完成并進(jìn)行響應(yīng),從用戶角度來(lái)看就是不會(huì)出現(xiàn)系統(tǒng)操作失敗或者訪問(wèn)超時(shí)等問(wèn)題,但是系統(tǒng)內(nèi)部可能會(huì)出現(xiàn)網(wǎng)絡(luò)延遲等問(wèn)題
-
P:Partition Tolerance 分區(qū)容錯(cuò)性:由于網(wǎng)絡(luò)的問(wèn)題錯(cuò)綜復(fù)雜,如果某個(gè)節(jié)點(diǎn)因?yàn)榫W(wǎng)絡(luò)等問(wèn)題造成數(shù)據(jù)不一致,或者數(shù)據(jù)延遲很久才同步過(guò)來(lái),雖然會(huì)影響部分節(jié)點(diǎn)數(shù)據(jù)的時(shí)效性,但是服務(wù)節(jié)點(diǎn)依然是可用的,分布式系統(tǒng)要能容忍這種情況的,也就是說(shuō),盡管網(wǎng)絡(luò)上有部分消息丟失,但系統(tǒng)仍然可繼續(xù)工作。
????????分布式系統(tǒng)中,CAP是無(wú)法同時(shí)滿足的,只能滿足CAP中的兩種,因此在設(shè)計(jì)分布式架構(gòu)時(shí),必須做出取舍,而對(duì)于分布式系統(tǒng),分區(qū)容忍性是基本要求,必須要滿足,否則就失去了價(jià)值。因?yàn)槭枪?jié)點(diǎn)宕機(jī)和網(wǎng)絡(luò)故障大概率事件,很難避免,而當(dāng)出現(xiàn)這種情況時(shí),不可能同時(shí)保持一致性和可用性,所以設(shè)計(jì)分布式系統(tǒng),就是在一致性和可用性之間取一個(gè)平衡。
????????那為什么說(shuō)在P滿足的情況下,為什么說(shuō)CA不能同時(shí)滿足呢?我們來(lái)通過(guò)假設(shè)看一看,如果CA同時(shí)滿足會(huì)怎么樣:
(1)假設(shè)現(xiàn)在要求滿足C(一致性),那么就是說(shuō)所有的節(jié)點(diǎn)在某一刻提供的數(shù)據(jù)都必須一致,我們知道在P的情況,是不可能保證的,要保證的話,就只能把其他節(jié)點(diǎn)全部干掉,比如禁止讀寫(xiě),那這其實(shí)就是和A是相悖的(某些節(jié)點(diǎn)雖然延遲,但是節(jié)點(diǎn)本身可用)
(2)假設(shè)現(xiàn)在要求滿足A(可用性),那么就是說(shuō)只要節(jié)點(diǎn)本身沒(méi)什么問(wèn)題,就可以對(duì)外提供服務(wù),哪怕有點(diǎn)數(shù)據(jù)延遲,很明顯這肯定是和C相悖的。
?2、一致性的類別:
????????CAP 是分布式事務(wù)處理的理論基礎(chǔ),在分布式事務(wù)的最終解決方案中一般選擇犧牲一致性來(lái)?yè)Q取可用性和分區(qū)容錯(cuò)性,但這里的 “犧牲一致性” 并不是完全放棄數(shù)據(jù)的一致性,而是放棄強(qiáng)一致性而換取弱一致性。一致性一般可以分為以下三種:
(1)強(qiáng)一致性:在任意時(shí)刻,所有節(jié)點(diǎn)中的數(shù)據(jù)是一樣的,系統(tǒng)中的某個(gè)數(shù)據(jù)被成功更新后,后續(xù)任何對(duì)該數(shù)據(jù)的讀取操作都將得到更新后的值。比如傳統(tǒng)數(shù)據(jù)庫(kù)的事務(wù)特性 ACID,就是追求強(qiáng)一致性模型。
一個(gè)集群需要對(duì)外部提供強(qiáng)一致性,就務(wù)必會(huì)損耗可用性,只要集群內(nèi)部某一臺(tái)服務(wù)器的數(shù)據(jù)發(fā)生了改變,那么就需要等待集群內(nèi)其他服務(wù)器的數(shù)據(jù)同步完成后,才能正常的對(duì)外提供服務(wù)。
(2)弱一致性:系統(tǒng)中的某個(gè)數(shù)據(jù)被更新后,后續(xù)對(duì)該數(shù)據(jù)的讀取操作可能得到更新后的值,也可能是更改前的值,但即使過(guò)了不一致時(shí)間窗口后,后續(xù)對(duì)該數(shù)據(jù)的讀取也不一定是最新值。
(3)最終一致性:是弱一致性的特殊形式,雖然不保證在任意時(shí)刻任意節(jié)點(diǎn)上的同一份數(shù)據(jù)都是相同的,但經(jīng)過(guò)一段時(shí)間后,所有服務(wù)節(jié)點(diǎn)間的數(shù)據(jù)最終會(huì)達(dá)到一致的狀態(tài)
弱一致性即使過(guò)了不一致時(shí)間窗口,后續(xù)的讀取也不一定能保證一致,而最終一致性過(guò)了不一致窗口后,后續(xù)的讀取一定保證一致。
3、什么是 BASE 理論:
????????BASE 理論是指,Basically Available(基本可用)、Soft-state( 軟狀態(tài))、Eventual Consistency(最終一致性),是基于CAP定理演化而來(lái),是對(duì)CAP中一致性和可用性權(quán)衡的結(jié)果。核心思想是即使無(wú)法做到強(qiáng)一致性,但每個(gè)業(yè)務(wù)根據(jù)自身的特點(diǎn),采用適當(dāng)?shù)姆绞絹?lái)使系統(tǒng)達(dá)到最終一致性。
-
BA 基本可用:指分布式系統(tǒng)在出現(xiàn)故障的時(shí)候,允許損失部分可用性,保證核心可用。但不等價(jià)于不可用。比如:搜索引擎0.5秒返回查詢結(jié)果,但由于故障,2秒響應(yīng)查詢結(jié)果;網(wǎng)頁(yè)訪問(wèn)過(guò)大時(shí),部分用戶提供降級(jí)服務(wù)等。
-
軟狀態(tài):軟狀態(tài)是指允許系統(tǒng)存在中間狀態(tài),并且該中間狀態(tài)不會(huì)影響系統(tǒng)整體可用性,即允許系統(tǒng)在不同節(jié)點(diǎn)間副本同步的時(shí)候存在延時(shí)。
-
最終一致性:系統(tǒng)中的所有數(shù)據(jù)副本經(jīng)過(guò)一定時(shí)間后,最終能夠達(dá)到一致的狀態(tài),不需要實(shí)時(shí)保證系統(tǒng)數(shù)據(jù)的強(qiáng)一致性。
????????很多時(shí)候我們并不要求數(shù)據(jù)的強(qiáng)一致性,而 BASE 通過(guò)犧牲強(qiáng)一致性來(lái)獲得更好的可用性,所以 BASE 理論的適用性更廣泛,比如更適合面向的是大型高可用可擴(kuò)展的分布式系統(tǒng)
柔性事務(wù)和剛性事務(wù):柔性事務(wù)滿足BASE理論(基本可用,最終一致),剛性事務(wù)滿足ACID理論。
二、一致性協(xié)議:
1、Gossip協(xié)議:
參考文章:https://juejin.cn/post/7023918632216297479
????????集群往往是由多個(gè)節(jié)點(diǎn)共同組成的,當(dāng)一個(gè)節(jié)點(diǎn)加入集群或者一個(gè)節(jié)點(diǎn)從集群中下線的時(shí)候,都需要讓集群中其他的節(jié)點(diǎn)知道,這樣才能將數(shù)據(jù)信息分享給新節(jié)點(diǎn)而忽略下線節(jié)點(diǎn)。
?????????如上圖,A、B、C 節(jié)點(diǎn)之間可以互相傳遞消息,但是D節(jié)點(diǎn)在下線之后會(huì)被廣播告訴其他存活節(jié)點(diǎn)。這樣的廣播協(xié)議就是今天要說(shuō)Gossip協(xié)議,Gossip協(xié)議也叫Epidemic協(xié)議(流行病協(xié)議),當(dāng)一個(gè)消息到來(lái)時(shí),通過(guò)Gossip協(xié)議就可以像病毒一樣感染全部集群節(jié)點(diǎn)。Gossip的過(guò)程是由一個(gè)種子節(jié)點(diǎn)發(fā)起的,當(dāng)一個(gè)種子節(jié)點(diǎn)有信息需要同步到網(wǎng)絡(luò)中的其他節(jié)點(diǎn)時(shí),它會(huì)隨機(jī)的選擇周圍幾個(gè)節(jié)點(diǎn)散播消息,收到消息的節(jié)點(diǎn)也會(huì)重復(fù)該過(guò)程,直至最終網(wǎng)絡(luò)中所有的節(jié)點(diǎn)都收到了消息。這個(gè)過(guò)程可能需要一定的時(shí)間,所以不能保證某個(gè)時(shí)間點(diǎn)所有的節(jié)點(diǎn)都有該條消息,但是理論上最終所有節(jié)點(diǎn)都會(huì)收到消息,因此它是一個(gè)最終一致性協(xié)議。
Gossip協(xié)議的特點(diǎn):
- (1)Gossip協(xié)議是周期性散播消息,每隔一段時(shí)間傳播一次
- (2)被感染的節(jié)點(diǎn),每次可以繼續(xù)散播N個(gè)節(jié)點(diǎn)
- (3)每次散播消息時(shí),都會(huì)選擇尚未發(fā)送過(guò)的節(jié)點(diǎn)進(jìn)行散播,不會(huì)向發(fā)送的節(jié)點(diǎn)散播
- (4)同一個(gè)節(jié)點(diǎn)可能會(huì)收到重復(fù)的消息,因?yàn)榭赡芡瑫r(shí)多個(gè)節(jié)點(diǎn)正好向它散播
- (5)集群是去中心化的,節(jié)點(diǎn)之間都是平等的
- (6)消息的散播不用等接收節(jié)點(diǎn)的 ack,即消息可能會(huì)丟失,但是最終應(yīng)該會(huì)被感染
下面我們來(lái)看個(gè)例子:
- ① 種子節(jié)點(diǎn)是A
- ② A節(jié)點(diǎn)選擇B、C節(jié)點(diǎn)進(jìn)行散播
- ③ C散播到D,B散播D和E,可以發(fā)現(xiàn)D收到兩次
- ④ D散播到F,最終整個(gè)網(wǎng)絡(luò)都同步到了消息
????????Gossip有點(diǎn)類似圖的廣度優(yōu)先遍歷算法,一般用于網(wǎng)絡(luò)拓?fù)浣Y(jié)構(gòu)信息的分享和維護(hù),比如 Redis 集群中節(jié)點(diǎn)的運(yùn)行狀態(tài)就是使用 Gossip 協(xié)議進(jìn)行傳遞的。
2、Raft一致性協(xié)議:
參考文章:https://baijiahao.baidu.com/s?id=1693824822611080380&wfr=spider&for=pc
????????分布式協(xié)議的難點(diǎn)之一就是數(shù)據(jù)的一致性,當(dāng)由多個(gè)節(jié)點(diǎn)組成的集群中只有一個(gè)節(jié)點(diǎn)收到數(shù)據(jù),我們就算成功的話,風(fēng)險(xiǎn)太大,當(dāng)要求所有節(jié)點(diǎn)都收到數(shù)據(jù)才響應(yīng)成功,性能又太差,所以一般會(huì)在數(shù)據(jù)的安全和性能之間做個(gè)折中,只要保證絕大部分節(jié)點(diǎn)同步數(shù)據(jù)成功,我們就算成功。比較知名的一致性算法有Raft算法,被廣泛應(yīng)用于許多中間件中,接下來(lái)我們就看看Raft算法是實(shí)現(xiàn)分布式系統(tǒng)的不同節(jié)點(diǎn)間的數(shù)據(jù)一致性的,也就是說(shuō)客戶端發(fā)送請(qǐng)求到任何一個(gè)節(jié)點(diǎn)都能收到一致的返回,當(dāng)一個(gè)節(jié)點(diǎn)出故障后,其他節(jié)點(diǎn)仍然能以已有的數(shù)據(jù)正常進(jìn)行。
????????首先介紹下在Raft算法中,幾種情況下每個(gè)節(jié)點(diǎn)對(duì)應(yīng)的角色:
(1)Leader節(jié)點(diǎn):同大多數(shù)分布式中的Leader節(jié)點(diǎn)一樣,所有數(shù)據(jù)的變更都需要先經(jīng)過(guò)Leader
(2)Follower節(jié)點(diǎn):Leader節(jié)點(diǎn)的追隨者,負(fù)責(zé)復(fù)制數(shù)據(jù)并且在選舉時(shí)候投票的節(jié)點(diǎn)
(3)Candidate候選節(jié)點(diǎn):參與選舉的節(jié)點(diǎn),就是Follower節(jié)點(diǎn)參與選舉時(shí)會(huì)切換的角色
Raft算法將一致性問(wèn)題分解為兩個(gè)的子問(wèn)題,Leader選舉 + 數(shù)據(jù)日志的復(fù)制:
2.1、Leader 選舉:
????????系統(tǒng)在剛開(kāi)始的時(shí)候,所有節(jié)點(diǎn)都是Follower節(jié)點(diǎn),這時(shí)都有機(jī)會(huì)參與選舉,將自己變成Candidate,變成Candidate的節(jié)點(diǎn)會(huì)先投自己1票,同時(shí)告訴其它節(jié)點(diǎn),讓它們來(lái)投票,當(dāng)拿到超過(guò)半數(shù)以上的投票時(shí),當(dāng)前Candidate就會(huì)變成Leader節(jié)點(diǎn)。但是如果每個(gè)Follower節(jié)點(diǎn)都變成Candidate那么就會(huì)陷入無(wú)限的死循環(huán),于是每個(gè)Follower都一個(gè)定時(shí)器,并且定時(shí)器的時(shí)間是隨機(jī)的,當(dāng)某個(gè)Follower的定時(shí)器時(shí)間走完之后,會(huì)確認(rèn)當(dāng)前是否存在Leader節(jié)點(diǎn),如果不存在再把自己變成Candidate。
- ① 由于A節(jié)點(diǎn)的定時(shí)器時(shí)間最短(10ms),所以A會(huì)成為Candidate。
- ② A投自己一票,并告訴B、C來(lái)投票,B、C也投出自己的同意票后,A就會(huì)變成Leader節(jié)點(diǎn),同時(shí)會(huì)記錄是第M任。這個(gè)M是做版本校驗(yàn)的,比如一個(gè)編號(hào)是10的節(jié)點(diǎn),收到了一個(gè)編號(hào)是9的節(jié)點(diǎn)的投票請(qǐng)求,那么就會(huì)拒絕這個(gè)請(qǐng)求。
????????在Leader節(jié)點(diǎn)選舉出來(lái)以后,Leader節(jié)點(diǎn)會(huì)不斷的發(fā)送心跳給其它Follower節(jié)點(diǎn)證明自己是活著的,其他Follower節(jié)點(diǎn)在收到心跳后會(huì)清空自己的定時(shí)器,并回復(fù)給Leader,因?yàn)榇藭r(shí)沒(méi)必要觸發(fā)選舉了。
????????如果Leader節(jié)點(diǎn)在某一刻掛了,那么Follower節(jié)點(diǎn)就不會(huì)收到心跳,因此在定時(shí)器到來(lái)時(shí)就會(huì)觸發(fā)新一輪的選舉,流程還是一樣。但是如果恰巧兩個(gè)Follower都變成了Candidate,并且都得到了同樣的票數(shù),那么此時(shí)就會(huì)陷入僵局,為了打破僵局,這時(shí)每個(gè)Candidate都會(huì)隨機(jī)推遲一段時(shí)間再次請(qǐng)求投票,當(dāng)然一般情況下,就是先來(lái)先得,優(yōu)先跑完定時(shí)器的Candidate理論成為L(zhǎng)eader的概率更大。
????????選舉流程大致如上,接下來(lái)我們來(lái)看看數(shù)據(jù)日志的復(fù)制。
2.2、數(shù)據(jù)日志的復(fù)制:
????????當(dāng)Leader節(jié)點(diǎn)收到客戶端Client的請(qǐng)求變更時(shí),會(huì)把變更記錄到log中,然后Leader會(huì)將這個(gè)變更隨著下一次的心跳通知給Follower節(jié)點(diǎn),收到消息的Follower節(jié)點(diǎn)把變更同樣寫(xiě)入日志中,然后回復(fù)Leader節(jié)點(diǎn),當(dāng)Leader收到大多數(shù)的回復(fù)后,就把變更寫(xiě)入自己的存儲(chǔ)空間,同時(shí)回復(fù)client,并告訴Follower應(yīng)用此log。至此,集群就變更達(dá)成了共識(shí)。
(1)正常情況下的日志復(fù)制:
- ① 一開(kāi)始,Leader 和兩個(gè) Follower 都沒(méi)有任何數(shù)據(jù)。
- ② 客戶端發(fā)送請(qǐng)求給 Leader,儲(chǔ)存數(shù)據(jù) “sally”,Leader 先將數(shù)據(jù)寫(xiě)在本地日志,這時(shí)候數(shù)據(jù)狀態(tài)還是 Uncommitted (還沒(méi)最終確認(rèn),使用紅色表示)
- ③ Leader 給兩個(gè) Follower 節(jié)點(diǎn)發(fā)送 AppendEntries 請(qǐng)求,數(shù)據(jù)在 Follower 上沒(méi)有沖突,則將數(shù)據(jù)暫時(shí)寫(xiě)在本地日志,Follower 的數(shù)據(jù)也還是 Uncommitted
- ④ Follower 將數(shù)據(jù)寫(xiě)到本地后,返回 OK。Leader 收到后成功返回,只要收到的成功的返回?cái)?shù)量超過(guò)半數(shù) (包含Leader),Leader 將數(shù)據(jù) “sally” 的狀態(tài)改成 Committed。( 這個(gè)時(shí)候 Leader 就可以返回給客戶端了)
- ⑤ Leader 再次給 Follower 發(fā)送 AppendEntries 請(qǐng)求,收到請(qǐng)求后,Follower 將本地日志里 Uncommitted 數(shù)據(jù)改成 Committed。這樣就完成了整個(gè)復(fù)制日志的過(guò)程,三個(gè)節(jié)點(diǎn)的數(shù)據(jù)是一致的,
(2)Network Partition 網(wǎng)絡(luò)分區(qū)情況下日志復(fù)制:
????????在 Network Partition 的情況下,部分節(jié)點(diǎn)之間沒(méi)辦法互相通信,Raft 也能保證這種情況下數(shù)據(jù)的一致性
① 一開(kāi)始有 5 個(gè)節(jié)點(diǎn)處于同一網(wǎng)絡(luò)狀態(tài)下,如下圖:
?② Network Partition 將節(jié)點(diǎn)分成兩邊,一邊有兩個(gè)節(jié)點(diǎn),一邊三個(gè)節(jié)點(diǎn):
?③ 兩個(gè)節(jié)點(diǎn)這邊已經(jīng)有 Leader 了,來(lái)自客戶端的數(shù)據(jù) “bob” 通過(guò) Leader 同步到 Follower。
?④ 只有兩個(gè)節(jié)點(diǎn),少于3個(gè)節(jié)點(diǎn),所以 “bob” 的狀態(tài)仍是 Uncommitted。所以在這里,服務(wù)器會(huì)返回錯(cuò)誤給客戶端
⑤ 另外一個(gè) Partition 有三個(gè)節(jié)點(diǎn),進(jìn)行重新選主。
⑥ 客戶端數(shù)據(jù) “tom” 發(fā)到新的 Leader2,并通過(guò)和上節(jié)網(wǎng)絡(luò)狀態(tài)下相似的過(guò)程,同步到另外兩個(gè) Follower;但因?yàn)檫@個(gè) Partition 有3個(gè)節(jié)點(diǎn),超過(guò)半數(shù),所以數(shù)據(jù) “tom” 都 Commit 了。
?⑦ 網(wǎng)絡(luò)狀態(tài)恢復(fù),5個(gè)節(jié)點(diǎn)再次處于同一個(gè)網(wǎng)絡(luò)狀態(tài)下。但是這里出現(xiàn)了數(shù)據(jù)沖突 “bob" 和 “tom"
⑧ 三個(gè)節(jié)點(diǎn)的 Leader2 廣播 AppendEntries
?⑨ 兩個(gè)節(jié)點(diǎn) Partition 的 Leader 自動(dòng)降級(jí)為 Follower,因?yàn)檫@個(gè) Partition 的數(shù)據(jù) “bob” 沒(méi)有 Commit,返回給客戶端的是錯(cuò)誤,客戶端知道請(qǐng)求沒(méi)有成功,所以 Follower 在收到 AppendEntries 請(qǐng)求時(shí),可以把 “bob“ 刪除,然后同步 ”tom”,通過(guò)這么一個(gè)過(guò)程,就完成了在 Network Partition 情況下的復(fù)制日志,保證了數(shù)據(jù)的一致性。
?
總結(jié)
以上是生活随笔為你收集整理的常见分布式理论(CAP、BASE)和一致性协议(Gosssip协议、Raft一致性算法)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 七种常见分布式事务详解(2PC、3PC、
- 下一篇: Java IO篇:什么是 Proacto