本文梳理從單點到分佈式遇到的概念及問題,包括:html
- 單點問題
- 主從
- 集羣
- 負載均衡
- 分佈式
- 分佈式理論:CAP,BASE
- 一致性:2PC,3PC,TCC,消息事務,Paxos,Raft
在架構風格:萬金油CS與分層中提到了CS架構風格。能夠說CS架構風格是分佈式架構的起點,因此咱們從CS架構風格開始。web
最簡單的CS架構就是一個Client+一個Server!Client和Server之間創建鏈接,而後Server對Client的請求進行響應。算法
對於這個最簡單的CS架構,有一個很明顯的問題:「單點問題」數據庫
即當這惟一的一個Server掛掉之後,Client就沒法得到響應了。那怎麼解決單點問題呢?很是簡單,冗餘。服務器
冗餘的方法有兩種:主從和集羣!網絡
注意:分佈式並非爲了解決單點問題的,而是爲了解決單臺服務器沒法支撐總體業務的問題。
主從、集羣和分佈式
下面舉個例子來講明,主從、集羣和分佈式的區別!架構
假設我老婆開了家飯店。由於沒錢,早期客戶也不是不少,因此就一我的張羅。這就是一個單點。由於若是我老婆有什麼事情,那就無法開店了。併發
但是我家有兩個小孩,總是生病,三天兩頭的要跑醫院,總是關門也不是辦法。因此,在老婆有事的時候,我就去開店。我和我老婆就是「主備關係」。負載均衡
可是呢,我也要上班,我不可能總是去開店。因此咱們都沒空的時候,就讓我丈母孃幫忙開店。如今我、我老婆和丈母孃之間的關係仍是「主備關係」!爲何?由於咱們沒有同時開店,只是在其餘人都有事的時候纔來開店的。也就是說同時只有一個服務對外提供服務。分佈式
一段時間後,飯店生意很好。老婆一我的有點忙不過來了。因而我就乾脆辭職和老婆一塊兒開店。咱們作的事情相同。因而咱們就組成了「集羣」。咱們同時對外提供相同的服務。
此時若是我老婆有事,那我又變成了一個單點服務。
再後來,咱們兩我的也忙不過來了。咱們就又招了個服務員。服務員主要工做就是幫忙點菜、收拾碗筷之類的。咱們就專心的作飯、收錢。如今我和我老婆之間仍是集羣,由於咱們的工做同樣。而我、我老婆和服務員就組成了分佈式。咱們三我的組成了完整的服務。
可是呢,如今服務員出現了單點問題。當這個服務員請假的話,咱們又忙不過來了。因而咱們又招了一個服務員。這兩個服務員之間又組成了集羣。
最後,飯店越開越大。咱們招了服務員、收銀、廚師、洗碗工、清潔員.....組成了一個大的分佈式系統。
而我和我老婆則出去浪去了。
三者的區別
從上面的例子,咱們能夠看出,主從、集羣和分佈式之間的區別:
- 主從:同時只有一臺服務對外提供服務。當這臺服務器掛掉之後,另一個服務器對外提供服務。
- 集羣:全部服務器同時對外提供服務。有一臺或幾臺服務器掛掉之後,可能有部分客戶端會受到影響(看負載均衡算法)
- 分佈式:全部的服務組合成一個完成的系統對外提供服務。若是有一個或多個服務掛掉,那對應的那部分功能就無法使用。每一個服務均可以經過集羣來確保可用性。
新的問題
雖然主從和集羣解決了單點的問題。可是從主從到集羣、再到分佈式,系統間通訊成指數級增加,也引入了各類其它問題。
在單點CS架構下,只有Client和Server之間存在網絡通訊,Server內部並不存在網絡通訊。而變成分佈式之後,Server間也須要經過網絡通訊。因爲網絡的不穩定,可能會出現各類問題。同時因爲節點數的增長,Server自己出問題的概率也就提升了,主要可能出現:
- 通訊異常:因爲網絡的不穩定性,可能致使服務間的通訊出現異常
- 網絡分區:因爲「通訊異常」,可能致使服務間的數據不一樣步,或者部分服務沒法對外服務。就是說,可能客戶端訪問到的響應有差別。
- 響應超時:通常來講,正常的調用會返回成功或失敗的狀態,可是網絡通訊可能出現超時。超時分爲
- 發送超時:請求並無到達服務端
- 響應超時:請求到達了服務端,可是服務端的響應並無返回到客戶端
- 處理方式:若是請求是冪等的,那能夠再次請求。若是不是冪等的,那須要一些補償措施。
- 節點故障:服務節點宕機,沒法對外提供服務。
- 節點選擇:即Client到哪一個節點去獲取數據。這就涉及到負載均衡算法,通常的負載均衡算法有(這裏不展開)
- 隨機
- 輪詢
- 加權隨機
- 加權輪詢
- 源地址Hash
- 一致性Hash
實際上在分佈式系統中,要解決的問題是:「在網絡不可靠的狀況下,如何保證數據一致性」?
處理方式有兩種:
- 想辦法保證強一致性
- 不保證強一致性,但保證最終一致性
強一致性方案
保證強一致性的思路其實很簡單,就是「假設網絡在大部分狀況下都是正常的,批量的去操做這一批節點,要麼所有成功,要麼所有失敗」!
操做方式有:
- 2PC(兩階段提交)
- 事務補償TCC(能夠說是業務層面的2PC)
- 3PC(三階段提交)
- Sagas:將分佈式長事務拆分紅多個短事務,由Sagas引擎來協調,具體沒有研究。可參考最後的參考資料。
2PC和3PC都引入了一個「協調者」來協調各個節點(參與者):
- 客戶端提交操做到協調者
- 協調者與參與者通訊,確保各個參與者的操做
- 若是全部參與者操做成功,協調者返回客戶端成功
- 不然協調者返回客戶端失敗
具體流程見下文。
2PC
流程:
- 提交請求階段(commit-request phase) :
- 協調者向全部參與者詢問是否能夠執行提交操做,而後開始等待各參與者的響應
- 參與者直接就開始執行事務操做,並將Undo信息和Redo信息寫入日誌
- 若是參與者的事務操做執行成功,則返回一個「贊成」消息;不然返回一個「終止」消息
- 提交階段(commit phase) :
- 當協調者從全部參與者得到的響應消息都爲「贊成」:
- 協調者向全部參與者發出「正式提交」的請求
- 參與者提交事務,並釋放事務佔用的資源
- 參與者向協調者發送「完成」消息
- 協調者收到全部參與者反饋的「完成」消息後,完成事務
- 若是任一參與者在第一階段返回「終止」消息,或者協調者在第一階段超時以前沒法獲取全部參與者的響應消息:
- 協調者向全部參與者發出「回滾操做」的請求
- 參與者利用以前寫入的Undo信息執行回滾操做,並釋放在整個事務期間佔用的資源
- 參與者向協調者發送「回滾完成」消息
- 協調者收到全部參與者反饋的「回滾完成」消息後,取消事務
舉例:
假設兩個Server(s1,s2)向三個註冊中心節點註冊(c1,c2,c3),若是是2PC,流程以下:
- s1向c1,c2,c3發送「提交請求」,c1,c2,c3接收到了消息,將s1信息保存,並寫入Undo和Redo日誌,返回「成功」
- 此時s2向c1,c2,c3發送「提交請求」,可是c1,c2,c3目前被鎖定了,因此只能等待
- s1收到全部的「成功」消息,向c1,c2,c3發送「確認提交」請求,c1,c2,c3提交事務,返回「完成」,s1事務結束
- s2超時沒等到全部的「成功」消息,事務回滾。
問題:
二階段提交的問題很明顯:
- 節點阻塞:在請求階段,節點就執行了事務操做,並進入阻塞狀態。這會致使幾個連鎖問題:
- 節點自己阻塞,在這個事務結束以前,這個節點不響應其它請求(上面的例子就是這種狀況)
- 若是節點佔用了公共資源,其它想要訪問公共資源的第三方節點也會進入阻塞狀態
- 若是在第二階段出現網絡故障,則節點會一直阻塞(可以使用超時機制)
- 數據不一致:在第二階段提交事務時,可能網絡故障了,只有部分節點提交了數據。這就致使了數據不一致。
- 超時失敗:第二階段,參與者執行完成了,並所有返回完成,可是協調者沒有接收到,致使執行了回滾操做
- 全部參與者都回滾了,事務執行失敗(實際事務都執行成功了,可是沒有接收到響應)
- 部分參與者回滾,又致使了數據不一致
因此2PC並不能保證真正的一致性。
XA是基於2PC制定的分佈式事務規範。JTA是基於XA實現的Java事務接口。
事務補償TCC
TCC將整個業務邏輯分爲三塊:Try、Confirm和Cancel三個操做:
- Try:對業務系統作檢測及資源預留。相似2PC的階段一
- Confirm:對業務系統作確認提交。默認只要Try成功,Confirm必定成功。
- Cancel:在業務執行錯誤時,執行的業務取消,釋放預留資源
舉例:
仍是假設兩個Server(s1,s2)向三個註冊中心節點註冊(c1,c2,c3),若是是TCC,流程以下:
- s1向c1,c2,c3發送「Try請求」,c1,c2,c3接收到了消息,鎖定服務列表信息,返回「成功」
- 此時s2向c1,c2,c3發送「Try請求」,鎖定失敗,能夠等待或重試
- s1收到全部的「成功」消息,向c1,c2,c3發送「Confirm提交」請求,c1,c2,c3提交事務,返回「完成」,s1事務結束
問題:
TCC的主要問題是適用性問題,由於是業務層的事務管理,因此須要針對具體的業務進行具體的Try/Confirm/Cancel的實現。
3PC
爲了解決2PC的阻塞問題,就有了三階段提交。三階段提交將二階段提交的「請求階段」拆分爲「CanCommit階段」和「PreCommit階段」。具體流程以下:
- CanCommit階段: 協調者向參與者發送提交請求,參與者若是能夠提交就返回「是」,不然返回「否」。(注意,這裏並不會執行事務,因此也不會阻塞)
- PreCommit階段:
- 若是參與者都返回「是」,則進行事務的預執行:
- 協調者向參與者發送PreCommit請求,並進入Prepared階段
- 參與者接收到PreCommit請求後,執行事務操做,並將undo和redo信息記錄到事務日誌中
- 若是參與者執行成功,則返回「完成」消息,並等待最終指令
- 假若有任何一個參與者向協調者發送了「否」,或者等待超時,那麼就中斷事務:
- 協調者向全部參與者發送終止請求
- 參與者收到終止請求後(或超時仍未收到協調者的請求),則終止事務
- DoCommit階段:該階段提交事務,也分爲兩種狀況:
- 若是協調者接收到全部參與者返回的「完成」,則從PreCommit狀態進入DoCommit狀態,同時向全部參與者發送doCommit請求
- 參與者接收到doCommit請求以後,提交事務,並在完成以後釋放全部的資源
- 事務提交完以後,向協調者發送「提交完成」響應
- 協調者接收到全部參與者的「提交完成」響應以後,完成事務
- 若是協調者沒有接收到全部參與者發送的「提交完成」響應(參與者返回的不是「提交完成」響應或者超時沒有返回任何信息),則終止事務
舉例:
依然假設兩個Server(s1,s2)向三個註冊中心節點註冊(c1,c2,c3),若是是3PC,流程以下:
- s1向c1,c2,c3發送「CanCommit請求」,c1,c2,c3接收到了消息,返回「OK」
- 此時s2向c1,c2,c3發送「CanCommit請求」,c1,c2,c3接收到了消息,也返回「OK」
- s1收到全部的「成功」消息,向c1,c2,c3發送「PreCommit請求」,c1,c2,c3將s1信息保存,並寫入Undo和Redo日誌,返回「成功」
- s2收到全部的「成功」消息,向c1,c2,c3發送「PreCommit請求」,c1,c2,c3返回「失敗」
- s1收到全部的「成功」消息,向c1,c2,c3發送「DoCommit請求」,c1,c2,c3提交事務,釋放資源,返回成功。事務完成
- s2收到「失敗」消息,事務回滾
問題:
3PC一樣會出現數據不一致的狀況,在第三階段協調者終止事務,可是參與者沒有接收到,則可能致使數據不一致。
最終一致性
能夠看到,強一致性在任何一個節點出現問題後,事務都會失敗。在事務要求不是很高的狀況下,並不必定要保證強一致性,只要保證最終一致性就能夠了。保證最終一致性的思路是基於CAP定理和BASE理論。
CAP定理
在《JDBC的架構設計》中提到了本地事務的ACID特性:
- 原子性(Atomicity):事務做爲一個總體被執行,包含在其中的對數據庫的操做要麼所有被執行,要麼都不執行
- 一致性(Consistency):事務應確保數據庫的狀態從一個一致狀態轉變爲另外一個一致狀態。一致狀態的含義是數據庫中的數據應知足完整性約束
- 隔離性(Isolation):多個事務併發執行時,一個事務的執行不該影響其餘事務的執行
- 持久性(Durability):已被提交的事務對數據庫的修改應該永久保存在數據庫中
CAP裏也有一個A和一個C。可是實際二者之間並無什麼關係。CAP中的C、A、P分別是:
- 一致性(Consistency):這裏的一致性指的是數據在多個副本之間保持強一致
- 可用性(Availability):指系統能夠對外提供服務,這是一個架構屬性。關於架構屬性可參考以前的文章《什麼是架構屬性》
- 分區容錯性(Partition tolerance):這裏的分區指的是「網絡分區」。指的是除非整個網絡環境都發生了故障,不然系統在遇到任何網絡分區故障的時候,仍然可以對外提供知足一致性和可用性的服務
CAP定理,說的是「對於一個分佈式系統來講,不可能同時知足一致性、可用性和分區容錯性。最多隻能知足其中兩項」!
那咱們應該知足哪兩項呢?這個都知道了,就是「分區容錯性」和「可用性」,同時保證「最終一致性」!那爲何呢?
咱們來假設:
- 假如放棄可用性:即系統遇到任何問題,就對外不可用。上面說了,分佈式系統網絡間通訊數量大大增長,若是網絡一波動,系統就不可用。那實際可用性還不如單點應用。那還要搞分佈式幹嗎?
- 假如放棄分區容錯性:避免網絡分區的方法就是將數據集中管理,又變成了單點應用了。
- 假如放棄強一致性:強一致性指的是像數據庫事務那樣,操做完了之後,全部的數據都是一致的。可是在分佈式系統裏面,若是出現了網絡分區或者網絡延時,那麼是沒法保證強一致性的。雖然放棄了強一致性,可是可使用各類手段來保證最終一致性。就是說當網絡故障恢復後,或者網絡通訊結束後,保證各個副本的數據一致。
BASE理論
BASE理論是CAP的實踐理論。其核心思想是:「根據CAP定理,咱們知道系統是沒法作到強一致性的,但系統能夠根據自身的業務特色,採用適當的方式來使系統達到最終一致。」
BASE包括:
- 基本可用(Basically Available):在系統出現故障時,相對於正常的系統來講,可能有某些服務降級,可是仍是能正常對外提供服務。服務降級包括:
- 響應時間:即比正常系統響應時間慢
- 功能:某些功能可能不可用。好比18年雙11,淘寶的地址服務就掛了,可是不影響用戶敗家,只是不能修改地址而已。
- 軟狀態(Soft State):指系統在最終一致以前的中間狀態(即數據在一部分節點中,但尚未同步到全部的節點),該狀態不影響系統的總體可用性。
- 最終一致性(Eventually Consistent):系統從軟狀態中,通過一段時間,最終須要達到數據一致。這個「時間」取決於網絡延時、系統負載、數據複製方案等因素。
能夠看出,如今的主要問題就是「如何保證最終一致性」?
最終一致性方案
保證最終一致性的方法有:
消息事務
消息事務的原理很簡單,經過消息隊列來保障最終一致性,大體流程爲:
- 在提交事務時,須要提交一份數據到消息隊列。二者要麼所有成功,要麼所有失敗
- 消息隊列消費端消費消息,執行後續的任務
- 若是執行成功則結束
- 若是由於網絡緣由執行失敗,則重試。若是由於業務緣由執行失敗,則能夠寫入一個補償消息。消息生產方進行數據回滾
舉例:
仍是假設Server(s1,s2)向三個註冊中心節點註冊(c1,c2,c3),消息事務流程以下:
- s1向c1和消息隊列提交註冊信息,提交成功
- s2向c1和消息隊列提交註冊信息,提交成功
- c2,c3監聽到消息隊列的消息,依次執行註冊信息
- 執行成功則c1,c2,c3的服務列表最終都是一致的
- 若是c2執行s2失敗,則須要向消息隊列發送一個撤銷操做,c1,c2接收到消息後,撤銷s2的信息,s2接收到消息後,事務失敗。
Paxos算法
廣泛認爲Paxos比較難理解,即便Lamport不使用任何公式寫的《Paxos Made Simple》論文也都比較難以理解。
我以爲《Paxos Made Simple》難以理解的緣由有兩個:
- 論文中沒有明確「提案」和「Value」之間的關係,前面說「Value」,後面又說「提案」。實際上「提案」包括了「提案編號」和「提案值」(也就是Value),提案編號是一個全序ID,即全局惟一且是遞增的。
- 論文裏面描述的Paxos算法分爲兩個階段,可是這裏的兩個階段和2PC裏所說的兩階段意義是不一樣的。2PC中的兩個階段是它的完整流程就是兩個階段,而Paxos裏的兩個階段是交替執行的,直到達到最終一致。也就是說,對一次Paxos計算來講,可能要通過屢次的階段1、階段二,纔會達到最終一致
論文中對Paxos算法的流程描述以下:
階段一:
- Proposer選擇一個提案號n,向大部分的Acceptor發送攜帶了提案號n的prepare請求
- 若是Acceptor接收到了prepare請求,請求攜帶的提案號n大於它所響應的prepare請求所攜帶的提案號,那麼它會返回一個響應,這個響應包含了它所經過的最大編號的提案(若是存在的話)
- ,並保證之後都不會再接收提案號小於n的請求了
- 階段二:
- 若是Proposer接收到了大部分Acceptor的響應,而後Proposer就發送accept請求給Acceptor,這個accept請求包含了提案號n和值v,這個v是前面Acceptor返回的最大編號的提案裏的值,若是Acceptor沒有返回任何提案,則v由Proposer自定義
- 若是Acceptor接收到了提案號爲n的accept請求,若是它沒有響應任何提案號大於n的prepare請求,它就接收這個提案
Paxos中有三個角色Proposer提出提案,Acceptor接收提案,Learner獲取提案
它主要保證了,在一次提案提交過程當中(也就是一個Paxos計算中):
- 只有提案被提交了,那麼它裏面的值才能被選中
- 最終只能有一個值被選中
- 若是某個進程獲取到了某個值,那麼這個值必定是被選中的那個值
舉例
下面我仍是以註冊中心的流程,來闡述BasicPaxos算法(MultiPaxos這裏不討論)!
在這裏Server能夠說是Proposer,註冊中心則是Acceptor,Client則是Learner。
假設有三個Server,P1[192.168.1.1],P2[192.168.1.2],P3[192.168.1.3]。五個註冊中心節點A1,A2,A3,A4,A5。三個客戶端L1,L2,L3。如今P1,P2都是第一次註冊到註冊中心(第一次計算):
- P1,P2從全局ID生成器那裏分別獲取一個提案編號,P1[100],P2[101]
- P1攜帶提案編號100向A1,A3,A5發送prepare請求。可是由於網絡不太好,A1,A3成功接收,可是A5發送失敗了。A1,A3接收到了提案,記錄下提案編號100,並保證之後不會再贊成編號小於100的提案。由於是第一次接收提案,因此A1,A3都沒有值返回。
- P2攜帶提案編號101向A1,A2,A5發送prepare請求。都發送成功了。A2,A5是第一次接收到提案,因此直接記錄下提案編號101,並保證之後不會再贊成編號小於101的提案。由於是第一次接收提案,因此A2,A5都沒有值返回。對於A1來講,由於已經接收到P1的提案,可是101大於100,因此記錄下101,並保證之後不會再贊成編號小於101的提案。雖然A1接收了P1的prepare請求,可是並無接收到任何值,因此也沒有返回。
- P1接收到了A1,A3的響應,可是沒有知足大多數。因此它從新獲取了一個提案編號120,準備從新發送。
- 在此以前,P2接收到了A1,A2,A5的響應,將本身的IP做爲值,並攜帶編號101一塊兒[101,[192.168.1.2]],向A1,A2,A5發送accept請求。A1,A2,A5都接收了這個提案,並記錄了下來。
- P1從新向A1,A3,A5發送prepare請求[120]。由於120大於A1,A3,A5所記錄的提案號,因此A1,A3,A5都記錄下來這個提案編號。因爲A1,A5已經記錄了P2的值,因此返回P2的值給P1。A3沒有返回。
- P1接收到了A1,A3,A5的響應,開始發送accept請求,可是A1,A5返回了P2的值,因此P1只能發送[120,[192.168.1.2]]到A1,A3,A5。
- 第一次計算結束,目前A1,A3,A5記錄的是[120,[192.168.1.2]]。A2記錄的是[101,[192.168.1.2]],雖然編號不同,可是值是同樣的。A4則能夠經過學習獲得最終的服務列表。
可是P1明顯沒有註冊上去,因此它又開始了第二次註冊嘗試(第二次Paxos計算),這時呢,P3也開始註冊了:
- P1,P3從全局ID生成器那裏分別獲取一個提案編號,P1[210],P3[211]
- P1攜帶提案編號210向A1,A3,A5發送prepare請求。A1,A3,A5接收到了提案,記錄下提案編號210,並保證之後不會再贊成編號小於210的提案。由於這裏是新的一次Paxos計算,因此這裏實際仍是第一次接收數據,因此不會返回提案值。
- P3攜帶提案編號211向A2,A4,A5發送prepare請求。由於211大於210,因此A2,A4,A5接收到了提案,記錄下提案編號211,並保證之後不會再贊成編號小於211的提案。這裏也不會返回提案值。
- P1接收到了響應,開始發送access請求[210,[192.168.1.1]]到A1,A3,A5。A1,A3接收了這個提案,可是A5的提案號如今是211,它不接收這個提案。
- P3接收到了響應,開始發送access請求[211,[192.168.1.3]]到A2,A4,A5。A2,A4,A5接收了這個提案。
- P1從新獲取了新的ID220,再次向A1,A3,A5發送prepare請求,A1,A3,A5都贊成了。A1,A3返回[210,[192.168.1.1]],A5返回[211,[192.168.1.3]]
- P1接收到響應,只能發送[220,[192.168.1.3]]的prepare請求到A1,A3,A5。A1,A3,A5所有贊成。
- 至此第二次計算結束,目前A1,A3,A5記錄的是[220,[192.168.1.3]]。P3,A2,A4記錄的是[211,[192.168.1.3]],雖然編號不同,可是值是同樣的。P2則經過學習能夠獲得最終的服務列表。
如今P1仍是沒註冊上去,因此再來第三次註冊嘗試(第二次Paxos計算),如今就它一個註冊了:
- P1從全局ID生成器那裏獲取一個提案編號P1[310]
- P1攜帶提案編號310向A1,A3,A5發送prepare請求。A1,A3,A5接收到了提案,記錄下提案編號310,並保證之後不會再贊成編號小於310的提案。由於這裏是新的一次Paxos計算,因此這裏實際仍是第一次接收數據,因此不會返回提案值。
- P1接收到了響應,開始發送access請求[310,[192.168.1.1]]到A1,A3,A5。A1,A3,A5接收了這個提案。
- 其它節點能夠經過學習,得到最終的服務列表。
Raft
Raft中也有三個角色:
- Leader(領袖):處理客戶端交互,通常一次只有一個Leader(若是出現網絡分區,可能會出現多個Leader,但不影響最終一致性)
- Follower(羣衆):默認狀況下都是Follower,Leader從Follower中選舉出來
- Candidate(候選人):將要被選爲Leader的Follower
Raft也分爲兩個階段:
- 選舉階段
- 由選舉出來的Learder負責和客戶端交互,同步各個Follower
整個過程和美國大選相似:
- 選舉階段(選總統)
- Follower在隨機等待一段時間後,轉換爲Candidate,當即先給本身投一票,而後向其它的Follower拉票,Follower進行投票,投票多的那個就是Leader
- 若是出現了兩個Candidate票數相同的,那麼就再等待一段時間,由這兩個Candidate再次拉票,票數多的就是Leader
- 選出來的Leader經過心跳機制和Follower確立leader地位。若是Leader掛了,則從新選出新的Leader(這個Leader的數據必須是最新的)
- Leader階段(總統處理國事,並公告)
- Leader接收到Client的消息後,此時爲Uncommitted狀態
- Leader向全部的Follower複製這個消息,並等待Follower的響應
- 當大多數的Follower返回後,Leader返回Client成功響應。此時爲Committed狀態
- Leader告知Follower,該數據已提交
舉例:
仍是假設Server(s1,s2)向三個註冊中心節點註冊(c1,c2,c3),Raft流程以下:
- c1,c2,c3先選舉出一個Leader,假設c1勝出
- c1和c2,c3創建心跳,並等待Server註冊
- s1發送註冊信息,c1接收,而後複製給c2和c3
- s2發送註冊信息,c1接收,而後複製給c2和c3。這裏至關於已經退化成了單CS架構了
- c1接收到c2,c3成功接收s1消息的響應,告知s1,事務成功
- 可是c2接收s2消息失敗,此時能夠嘗試重試,或者回滾事務
一致性方案選擇
「強一致性」較「最終一致性」可靠性和性能都較差(Paxos因爲邏輯複雜性能也不行),可是實現簡單,「最終一致性」則反之。方案的選擇,視具體狀況而定:
- 對於須要強一致性的業務來講,則放棄部分性能,使用強一致性。好比轉帳業務
- 對於性能要求高,可是數據一致性要求並非太強的業務,可使用最終一致性。好比大V發微博
參考資料
- 《PaxosMadeSimple》http://lamport.azurewebsites.net/pubs/pubs.html#paxos-simple
- 《Base: An Acid Alternative》https://queue.acm.org/detail.cfm?id=1394128
- Wiki二階段提交https://zh.wikipedia.org/wiki/%E4%BA%8C%E9%98%B6%E6%AE%B5%E6%8F%90%E4%BA%A4
- Wiki三階段提交https://zh.wikipedia.org/wiki/%E4%B8%89%E9%98%B6%E6%AE%B5%E6%8F%90%E4%BA%A4
- Wiki XAhttps://zh.wikipedia.org/wiki/X/Open_XA
- Sagashttps://www.cs.cornell.edu/andru/cs711/2002fa/reading/sagas.pdf
- CONSENSUS: BRIDGING THEORY AND PRACTICEhttps://ramcloud.stanford.edu/~ongaro/thesis.pdf