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