都在大談分布式,可分布式底層實現(xiàn)原理你知道嗎?一文總結(jié),

首先得放該開頭,分布式系統(tǒng)的一致性協(xié)議一直是分布式系統(tǒng)的難題,本人沒有閱讀過 Lamport 老人家的論文原文(估計直接讀也未必讀的懂),以下所有內(nèi)容來自網(wǎng)絡(luò)博文、書籍和網(wǎng)站的整理,加上自己的理解潤色。水平有限不敢說全都正確,僅供參考。

Paxos

說到分布式一致性協(xié)議,Paxos 肯定是繞不開的,關(guān)于它和其作這 Lamport 的傳奇故事也是有很多,這里就不啰嗦了,感興趣的可以自行搜索。作為幾種常見協(xié)議的基礎(chǔ),Paxos 提供了“選舉” 的思想,Lamport 為了簡化 Paxos,也為了講述這個算法,假想了一個叫做 Paxos 的希臘城邦進行選舉的情景,這個算法也是因此而得名。

Paxos 算法的步驟是這樣:

首先有兩種角色,一個是“提議者”,一個是“接受者”。提議者可以向接受者提出提議,然后接受者表達意見。

因為存在多個提議者,如果同時表達意見會出現(xiàn)意見不一致的情況,所以首先需要盡快選出一個領(lǐng)導(dǎo)者,讓意見統(tǒng)一。

然后領(lǐng)導(dǎo)者會給接受者發(fā)出提議,如果一個提議被大多數(shù)接受者接納,這個提議就通過了。

大致的流程是這樣,再完善一下細節(jié):

如何明確領(lǐng)導(dǎo)者?這里會有兩個階段:

第一階段是先達成一致,協(xié)商出領(lǐng)導(dǎo)者,具體方法就是通過編號,提議者會先報告一個編號,誰的編號最大誰就是領(lǐng)導(dǎo)(Lamport 巧妙的比喻為“賄選”,誰出的錢多就選誰)。

然后第二階段就是上一輪勝出的領(lǐng)導(dǎo)提出提議,發(fā)送給各個接受者。

跟常識不太一樣的是,每個提議者不會執(zhí)著于當領(lǐng)導(dǎo),而是謀求盡快達成共識,所以如果在一個提議者提議的時候,如果發(fā)現(xiàn)接受者已經(jīng)接受了其他領(lǐng)導(dǎo)者的提議,也會默默的把自己的提議改為前面領(lǐng)導(dǎo)者的提議。

編號不能太小,很小的話前兩個階段都會直接失敗,接受者拒絕接受你的提議。

在步驟 2 中,還有可能出現(xiàn)沖突:比如如果一個提議者在對接受者 A 提議的時候,發(fā)現(xiàn) A 接受了領(lǐng)導(dǎo)者 L1 的提議,然后又去接受者 B 那里提議,發(fā)現(xiàn) B 接受了領(lǐng)導(dǎo)者 L2 的提議,已知這個提議者肯定會跟隨前面已經(jīng)存在的提議,那么他會把自己的提議改為上面兩個的哪個吶?答案是數(shù)值更大的那個。

在達成共識之前,這整個階段,哪個提議者先來,哪個后來,接受者什么時候收到提議者的信息,都是不可控的。所以有可能產(chǎn)生這樣一種情況:一個提議者已經(jīng)晉升為領(lǐng)導(dǎo)者,但是還沒發(fā)起提議,這時候另外一個“土豪”提議者過來,瘋狂“賄選”,還是存在機會讓自己勝出的。這時就形成了一種博弈:

上一個領(lǐng)導(dǎo)者要趕在土豪提議者賄賂到接受者前,趕到接受者面前讓他接受自己的提議,否則會因為自己的之前賄賂的錢比土豪少而被拒絕。

土豪“提議者”要趕在上一個領(lǐng)導(dǎo)者將提議傳達給接受者前,賄賂到接受者,否則土豪提議者即便賄賂成功,也要默默的將自己的提議改為前任意見領(lǐng)袖的提議。

這整個博弈的過程,最終就看這兩個提議者誰的進展快了。但最終一定會有一個領(lǐng)導(dǎo)者,先得到多數(shù)接受者的認可,那他的提議就勝出了。

總結(jié)來看,Paxos 包括以下幾個原則:

Paxos 算法包括兩個階段:第一個階段主要是賄選,還沒有提出提議;第二個階段主要根據(jù)第一階段的結(jié)果,明確接受誰的提議,并明確提議的內(nèi)容是什么(這個提議可能是賄選勝出提議者自己的提議,也可能是前任意見領(lǐng)袖的提議,具體是哪個提議,往下看,見下面第 3 點的內(nèi)容)。

編號(賄賂金額)很重要,無論在哪個階段,編號(賄賂金額)小的,都會被拒絕。

在第一階段中,一旦接受者已經(jīng)接受了之前領(lǐng)導(dǎo)者的提議,那后面再來找這個接受者的提議者,即便在賄賂中勝出,也要被洗腦,默默將自己的提議改為前任意見領(lǐng)袖的提議,然后他會在第二階段提出該提議(也就是之前意見領(lǐng)袖的提議,以力爭讓大家的意見趨同)。如果接受者之前沒有接受過任何提議,那賄選勝出的提議者就可以提出自己的提議了。

以上,我們說的 Paxos 其實又叫 Basic Paxos,只具備理論基礎(chǔ),實際上實現(xiàn)起來很麻煩而且效率低。因為每次同步一個信息,就要進行上述繁雜的達成共識階段,無異會產(chǎn)生巨大的開銷。

于是后來又有了進階版的 Multi Paxos 協(xié)議。只要 Leader 是相對穩(wěn)定不變的,第 1 階段就變得不必要。 這樣,系統(tǒng)可以在接下來的 Paxos 算法實例中,跳過的第 1 階段,直接使用同樣的 Leader。

Multi Paxos 本身對一些邊緣情況沒有定義,所以大多數(shù)實際應(yīng)用是基于 Multi Paxos 進行補充,或者使用它的變種 Raft。

從網(wǎng)上查詢得知,工業(yè)界中三種協(xié)議的應(yīng)用情況基本如下:

微信背后的高可用存儲系統(tǒng) PaxosStore 是基于 Multi Paxos 開發(fā)的

廣為人知的高可靠的 kv 存儲系統(tǒng) etcd 用的 Raft

阿里的高性能存儲 PolarFS 用到的 Raft 變種 ParallelRaft 協(xié)議

TiDB 用的 Raft

ZAB 的名字就叫 ZooKeeper Atomic Broadcast,自然是 ZooKeeper 在用,沒找到其他在用的,但是考慮到動物管理員恐怖的占有率,ZAB 協(xié)議也不容輕視

Raft 協(xié)議

Raft 感覺是最容易理解的一個了,也很有意思。先說它的邏輯:

Raft 協(xié)議的每個副本都會處于三種狀態(tài)之一:Leader、Follower、Candidate。

Leader:所有請求的處理者,Leader 副本接受 client 的更新請求,本地處理后再同步至多個其他副本?Follower:請求的被動更新者,從 Leader 接受更新請求,然后寫入本地日志文件?Candidate:如果 Follower 副本在一段時間內(nèi)沒有收到 Leader 副本的信條,則判斷 Leader 可能已經(jīng)故障,此時啟動選主過程,此時副本會變成 Candidate 狀態(tài),直到選主結(jié)束。

可以看出,跟 Paxos 的基本理念一樣,首先最基本的 Flollow(接受者),如果 Follower 接收不到 Leader 的心跳,就會全部轉(zhuǎn)化為Candidate(提議者),然后提議者開始“賄選”,直到選出 Leader 之后,所有沒選上的 Candidate 退回到 Follower 狀態(tài),統(tǒng)一接收 Leader 領(lǐng)導(dǎo)。

就是說只要 Leader 不掛掉,只要選舉一次就行了,后面大家默認信任選出來的 Leader。

另外,每一個副本都會維護一個 term,類似于一個邏輯時鐘,每發(fā)生一個動作就會遞增,通過比較每個提議的 term,副本會默認使用最新的 term,防止發(fā)生沖突。如果一個 Leader 或者 Candidate 發(fā)現(xiàn)自己的 term 不是最新的了,就會自動降級到 Follower,而如果一個 Follower 接受到低于自己當前 term 的提議,就會直接拋棄。

基本原則了解之后,我們完善一下細節(jié)。

在強 Leader 的幫助下,Raft 將一致性問題分解為了三個子問題:

Leader 選舉:當已有的 Leader 故障時必須選出一個新的 Leader。

日志復(fù)制:Leader 接受來自客戶端的命令,記錄為日志,并復(fù)制給集群中的其他服務(wù)器,并強制其他節(jié)點的日志與 Leader 保持一致。

安全 safety 措施:通過一些措施確保系統(tǒng)的安全性,如確保所有狀態(tài)及按照相同順序執(zhí)行相同命令的措施。

另外丟兩個非常清晰的 Raft 全流程動畫演示,看完之后很容易理解:

http://thesecretlivesofdata.com/raft/

https://raft.github.io/

選舉過程

我們從最初始的狀態(tài)來模擬,假設(shè)一個集群有三個副本,剛啟動的時候,大家都是 Follower。然后每個 Follower 會有一個倒計時(election timeout),在倒計時結(jié)束之前,如果沒有收到任何 Leader 的心跳,或者其他 Candidate 的投票請求,就會轉(zhuǎn)化為 Candidate,開始選舉。

變成 Candidate 之后,會先投自己一票,同時開啟一個倒計時,然后向所有其他節(jié)點發(fā)起投票請求。如果在倒計時完成之前,沒有成為 Leader 或者接收到其他 Leader 的消息,就會發(fā)起新一輪選舉。

當一個副本處于 Candidate 狀態(tài)時,如果收到來自 Leader 的心跳消息,就會立即變身為 Follower。如果發(fā)出去的投票請求得到了半數(shù)節(jié)點的成功回應(yīng),就會立即變身為 Leader,并周期性地向其它節(jié)點廣播心跳消息,以盡可能長期維持自己的統(tǒng)治地位。

關(guān)于選舉的更多細節(jié):

election timeout 會是一個一定范圍內(nèi)的隨機值,因為如果所有節(jié)點的倒計時時間都一樣,大家就會同時變成 Candidate,然后同時互相投票選舉,加大了達成共識的難度,所以倒計時會稍微錯開,就很容易率先選出來一個 Leader。

成功選舉 Leader 之后,Leader 會向所有節(jié)點發(fā)送心跳,然后心跳會重置每個節(jié)點的 election timeout 倒計時時間。

即便錯開了倒計時,仍然有可能出現(xiàn)多個 Candidate 同時競爭,如果兩個 Candidate 獲得的票數(shù)不一致還好說,其中一個必然是多數(shù),變成了 Leader。但是如果恰巧節(jié)點總數(shù)是偶數(shù),就有可能出現(xiàn)票數(shù)一樣僵持的情況。這時候就會重新選舉。(這里我覺得每個 Candidate 發(fā)一個隨機數(shù)過去,誰更大聽誰的也行...,當然即便這樣也有可能一樣大)

數(shù)據(jù)同步

節(jié)點選出來了,下面就應(yīng)該進行數(shù)據(jù)同步了。當一個數(shù)據(jù)修改的請求過來,會直接找到 Leader 節(jié)點,所有的增刪改查都由 Leader 受理。然后同步給各個 Follower。

每次數(shù)據(jù)同步操作同時也是一個心跳,會更新 Follower 的 election timeout。另外只有當多數(shù)節(jié)點返回同步成功之后,Leader 才會給客戶端返回操作成功。

分區(qū)容錯

然后是最麻煩的部分,如果出現(xiàn)了網(wǎng)絡(luò)分區(qū)怎么辦?比如原本五個節(jié)點的集群,被分成了雙節(jié)點和三節(jié)點的兩個集群。

假設(shè)原本的 Leader 在雙節(jié)點的集群里面,那么這個集群會照常運作。而新出現(xiàn)的三個節(jié)點的集群,由于沒有收到心跳,會開始選舉,然后選出新的 Leader。這時候,如果有客戶端發(fā)起請求,有可能發(fā)送到兩個不同的 Leader 上面,如果發(fā)送到原來的那個 Leader 上,即雙節(jié)點的集群中,Leader 把操作同步給 Follower,會發(fā)現(xiàn)收不到足夠多的 Follower 響應(yīng)(因為這個 Follower 還以為自己的集群是五個節(jié)點),然后就沒辦法同步數(shù)據(jù)。而三節(jié)點的新集群,就可以順利更新數(shù)據(jù)。

如果這時候網(wǎng)絡(luò)恢復(fù)了,各個節(jié)點又可以正常通信,三節(jié)點集群中的 Leader 和 雙節(jié)點集群中的 Leader 會互相通信,然后會發(fā)現(xiàn)三節(jié)點的 Leader 由于一直正常運行,term 值會不斷增大,所以大家會采信他的數(shù)據(jù)。于是雙節(jié)點的兩臺機器會回滾,然后全部接受新 Leader 的數(shù)據(jù)同步。

ZAB 協(xié)議

了解了上面兩種協(xié)議之后, ZAB 協(xié)議學(xué)習(xí)起來也不復(fù)雜。ZAB 協(xié)議定義了選舉(election)、發(fā)現(xiàn)(discovery)、同步(sync)、廣播(Broadcast)四個階段。

選舉(election)是選出哪臺為主機;

發(fā)現(xiàn)(discovery)、同步(sync)當主選出后,要做的恢復(fù)數(shù)據(jù)的階段;

廣播(Broadcast)當主機和從選出并同步好數(shù)據(jù)后,正常的主寫同步從寫數(shù)據(jù)的階段。

跟其他協(xié)議類似,集群副本有三種狀態(tài):

Leader 也就是領(lǐng)導(dǎo)者

Follower 也就是接受提議的跟隨者

Observer 可以認為是領(lǐng)導(dǎo)者的的 Copy,不參與投票,在這可以忽略

與之對應(yīng)的,一個 ZK 集群中的某個節(jié)點也有三種狀態(tài):

Looking:選舉狀態(tài),當前群龍無首

Leading:Leader 節(jié)點才有的狀態(tài)

Following:Follower 節(jié)點才有的狀態(tài)

Observing:觀察者狀態(tài)。表明當前服務(wù)器角色是 Observer,與 Folower 唯一的不同在于不參與選舉,也不參與集群寫操作時的投票。

每次寫成功的消息,都有一個全局唯一的標識,叫 zxid。是 64 bit 的正整數(shù),高 32 為啥 epoch 表示選舉紀元,低 32 位是自增的 id,每寫一次加一。一個博主巧妙地比喻為為中國古代的年號,非常形象,例如萬歷十五年,萬歷是 epoch,十五年是 id。

ZK 集群一般都是奇數(shù)個機器(2n+1),只有一個領(lǐng)導(dǎo)者 Leader,其余都是跟隨者 Follower。選主還是寫數(shù)據(jù),要有大于等于 n+1 臺選舉相同,才能執(zhí)行選舉的操作。所有的寫操作必須要通過 Leader 完成再由 Leader 將寫操作廣播給其它服務(wù)器。

選舉

當集群新建,或者主機死機,或者主機與一半或以上的從機失去聯(lián)系后,都會觸發(fā)選擇新的主機操作。

選舉有多種算法,到3.4.10版本為止,可選項有:

0 基于UDP的LeaderElection

1 基于UDP的FastLeaderElection

2 基于UDP和認證的FastLeaderElection

3 基于TCP的FastLeaderElection

在3.4.10版本中,默認值為 3,也即基于 TCP 的 FastLeaderElection。另外三種算法已經(jīng)被棄用,并且有計劃在之后的版本中將它們徹底刪除而不再支持。

FastLeaderElection

這是 ZAB 默認采用的算法。

每次選舉都要把選舉輪數(shù)加一,類似于 zxid 里的 epoch 字段,防止不同輪次的選舉互相干擾。

每個進入 Looking 狀態(tài)的節(jié)點,會先把投票箱清空,然后通過廣播投票給自己,再把投票消息發(fā)給其它機器,同時也在接受其他節(jié)點的投票。投票信息包括:輪數(shù)、被投票節(jié)點的 zxid,被投票節(jié)點的編號等等。

其他 Looking 狀態(tài)的節(jié)點收到后:

首先判斷票是否有效。是否有效的方法為看票的投票輪數(shù)和本地記載的投票輪數(shù)是否相等:

如果比本地投票輪數(shù)的小,丟棄。

如果比本地投票輪數(shù)的大,證明自己投票過期了,清空本地投票信息,更新投票輪數(shù)和結(jié)果為收到的內(nèi)容。通知其他所有節(jié)點新的投票方案。

如果和本地投票輪數(shù)相等,按照投票的優(yōu)先級比較收到的選票和自己投出去的選票:

如果收到的優(yōu)先級大,則更新自己的投票為對方發(fā)過來投票方案,把投票發(fā)出去。

如果收到的優(yōu)先級小,則忽略該投票。

如果收到的優(yōu)先級相等,則更新對應(yīng)節(jié)點的投票。

每收集到一個投票后,查看已經(jīng)收到的投票結(jié)果記錄列表,看是否有節(jié)點能夠達到一半以上的投票數(shù)。如果有達到,則終止投票,宣布選舉結(jié)束,更新自身狀態(tài)。然后進行發(fā)現(xiàn)和同步階段。否則繼續(xù)收集投票。

投票終止后,服務(wù)器開始更新自身狀態(tài)。若過半的票投給了自己,則將自己的服務(wù)器狀態(tài)更新為 Leading,否則將自己的狀態(tài)更新為 Following。

廣播——主從同步

主從同步數(shù)據(jù)比較簡單,當有寫操作時,如果是從機接收,會轉(zhuǎn)到主機,保證寫都是在主機上進行。Leader 會先提議事務(wù),收到過半回復(fù)后,再發(fā)提交。

當 Leader 收到寫操作時,先本地生成事務(wù)為事務(wù)生成 zxid,然后發(fā)給所有 Follower 節(jié)點。

當 Follower 收到事務(wù)時,先把提議事務(wù)的日志寫到本地磁盤,成功后返回給 Leader。

Leader 收到過半反饋后對事務(wù)提交。再通知所有的 Follower 提交事務(wù), Follower 收到后也提交事務(wù),提交后就可以對客戶端進行分發(fā)了。

Raft\ZAB共同點和區(qū)別

首先,二者都是通過選舉一個 Leader 來簡化復(fù)雜度,后續(xù)的工作都是由 Leader 來做。

投票的時候,二者都需要定義一個輪次

Raft 定義了 term 來表示選舉輪次

ZooKeeper 定義了 electionEpoch 來表示

同步數(shù)據(jù)的時候,都希望選舉出來的 Leader 至少包含之前全部已提交的日志。

那如何能包含之前的全部日志?我們可以通過判斷 Leader 節(jié)點中日志的邏輯時間序列,包含越新、越多日志的節(jié)點,越有可能包含之前全部的已提交日志。對于兩種協(xié)議:

Raft:term 大的優(yōu)先,然后 entry 的 index 大的優(yōu)先

ZooKeeper:peerEpoch 大的優(yōu)先,然后 zxid 大的優(yōu)先

ZooKeeper 有 2 個輪次,一個是選舉輪次 electionEpoch,另一個是日志的輪次 peerEpoch(即表示這個日志是哪個輪次產(chǎn)生的)。而 Raft 則是只有一個輪次,相當于日志輪次和選舉輪次共用了。

但是有一個問題,日志越新越大的比較方式能滿足我們“Leader 至少包含之前全部已提交的日志”的愿望嗎?

對于 Raft 協(xié)議,特殊情況下不能。對于 Raft 協(xié)議,通過兩個約束來保證一致性:

當前 term 的 Leader 不能“直接”提交之前 term 的 entries。

必須要等到當前 term 有 entry 過半了,才順便一起將之前 term 的 entries 進行提交。

至于為什么必須這樣,在什么特殊情況下會出問題,這篇文章中給了詳細說明:Raft算法賞析建議直接看里面的例子,有點長我就不抄過來了。

但是對于 ZooKeeper 是不會出現(xiàn)這種情況的,因為 ZooKeeper 在每次 Leader 選舉完成之后,都會進行數(shù)據(jù)之間的同步糾正,所以每一個輪次,大家都認知內(nèi)容都是統(tǒng)一的。

繼續(xù)對比,二者的選舉效率也不同:

Raft 中的每個節(jié)點在某個 term 輪次內(nèi)只能投一次票,那個 Candidate 先請求投票誰就可能先獲得投票,這樣就可能造成分區(qū),即各個 Candidate 都沒有收到過半的投票,Raft 通過 Candidate 設(shè)置不同的超時時間,來快速解決這個問題,使得先超時的Candidate(在其他人還未超時時)優(yōu)先請求來獲得過半投票。

ZooKeeper 中的每個節(jié)點,在某個 electionEpoch 輪次內(nèi),可以投多次票,只要遇到更大的票就更新,然后分發(fā)新的投票給所有人。這種情況下不存在分區(qū)現(xiàn)象,同時有利于選出含有更新更多的日志的 Server,但是選舉時間理論上相對 Raft 要花費的多。

在一個節(jié)點啟動后,如何加入一個集群(這里是說本來就在集群配置內(nèi)的一個節(jié)點):

Raft:比較簡單,該節(jié)點啟動后,會收到 Leader 的 AppendEntries RPC,在這個 RPC 里面包含 Leader 信息,可以直接識別。

ZooKeeper:啟動后,會向所有的其他節(jié)點發(fā)送投票通知,然后收到其他節(jié)點的投票。該節(jié)點只需要判斷上述投票是否過半,過半則可以確認 Leader。

關(guān)于 Leader 選舉的觸發(fā):

首先集群啟動的時候,二者肯定都要先進行選舉。

如果選舉完成后,發(fā)生了超時:

Raft:目前只是 Follower 在檢測。如果 Follower 在倒計時時間內(nèi)未收到 Leader 的心跳信息,則 Follower 轉(zhuǎn)變成 Candidate,自增 term 發(fā)起新一輪的投票。

ZooKeeper:Leader 和 Follower 都有各自的檢測超時方式,Leader 是檢測是否過半 Follower 心跳恢復(fù)了,F(xiàn)ollower 檢測 Leader 是否發(fā)送心跳了。一旦 Leader 檢測失敗,則 Leader 進入 Looking 狀態(tài),其他 Follower 過一段時間因收不到 Leader 心跳也會進入 Looking 狀態(tài),從而出發(fā)新的 Leader 選舉。一旦 Follower 檢測失敗了,則該 Follower 進入 Looking 狀態(tài),此時 Leader 和其他 Follower 仍然保持良好,則該 Follower 仍然是去學(xué)習(xí)上述 Leader 的投票,而不是觸發(fā)新一輪的 Leader 選舉。

關(guān)于上一輪次 Leader 殘存的數(shù)據(jù)怎么處理:

包括兩種數(shù)據(jù):

已過半復(fù)制的日志

未過半復(fù)制的日志

Raft:對于之前 term 的過半或未過半復(fù)制的日志采取的是保守的策略,全部判定為未提交,只有當前 term 的日子過半了,才會順便將之前 term 的日志進行提交

ZooKeeper:采取激進的策略,對于所有過半還是未過半的日志都判定為提交,都將其應(yīng)用到狀態(tài)機中

Raft 的保守策略更多是因為 Raft 在 Leader 選舉完成之后,沒有同步更新過程來保持和 Leader 一致(在可以對外處理請求之前的這一同步過程)。而 ZooKeeper 是有該過程的。

在對正常請求的處理方式上,二者都是基本相同的,大致過程都是過半復(fù)制。

對于正常請求的消息順序保證:

Raft:對請求先轉(zhuǎn)換成 entry,復(fù)制時,也是按照 Leader 中 log 的順序復(fù)制給 Follower 的,對 entry 的提交是按 index 進行順序提交的,是可以保證順序的

ZooKeeper:在提交議案的時候也是按順序?qū)懭敫鱾€ Follower 對應(yīng)在 Leader 中的隊列,然后 Follower 必然是按照順序來接收到議案的,對于議案的過半提交也都是一個個來進行的

如果是 Leader 掛了之后,重新選舉出 Leader,會不會有亂序的問題?

Raft:Raft 對于之前 term 的 entry 被過半復(fù)制暫不提交,只有當本 term 的數(shù)據(jù)提交了才能將之前 term 的數(shù)據(jù)一起提交,也是能保證順序的

ZooKeeper:ZooKeepe r每次 Leader 選舉之后都會進行數(shù)據(jù)同步,不會有亂序問題

在出現(xiàn)網(wǎng)絡(luò)分區(qū)情況下的應(yīng)對措施,二者都是相同的:

目前 ZooKeeper 和 Raft 都是過半即可,所以對于分區(qū)是容忍的。如5臺機器,分區(qū)發(fā)生后分成 2 部分,一部分 3 臺,另一部分 2 臺,這 2 部分之間無法相互通信。

其中,含有 3 臺的那部分,仍然可以湊成一個過半,仍然可以對外提供服務(wù),但是它不允許有節(jié)點再掛了,一旦再掛一臺則就全部不可用了。

含有 2 臺的那部分,則無法提供服務(wù),即只要連接的是這 2 臺機器,都無法執(zhí)行相關(guān)請求。

所以 ZooKeeper 和 Raft 在一旦分區(qū)發(fā)生的情況下是是犧牲了高可用來保證一致性,即 CAP 理論中的 CP,二者都是 CP 系統(tǒng)。

必須需要重申,無論上面哪一種協(xié)議,都只是概念模型,還有很多細節(jié)需要補充完善,比如具體的數(shù)據(jù)存儲方式,日志處理,具體的節(jié)點通信方式等等,距離實現(xiàn)一個工業(yè)可用的框架還有一段距離,想了解具體細節(jié)可以參考各個大廠開源的產(chǎn)品,或者自己嘗試實現(xiàn)一下。

就像文章中提到比較多的技術(shù)--zookeeper,我在日常工作中用得到的是比較多的,不得不說,雖然有很多人吐槽他,但是在我看來是真的好用啊,所以,對于分布式底層技術(shù)要求學(xué)習(xí)比較強烈的,建議你看一下下面這份文檔,真的,強烈建議

分布式架構(gòu)

paxos協(xié)議

實戰(zhàn)

需要這份資料的,關(guān)注+轉(zhuǎn)發(fā)后,私信“資料”即可查看獲取方式

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容