基本原則與設計理念
原教旨CAP理論
CAP是什么:
- C:強一致性,在分布式多副本情況加,對數據的根性與單副本是一樣的。
- A:可用性,即容錯,任何時刻都能在一定事件內完成服務
- P:分區容忍性,出現網絡分區現象,即分區間的機器無法通信,這種情況仍然能夠繼續工作。
為什么CAP三者不能兼得?因為在通常網絡下,P是必然會發生的,我們可以將問題轉換為:若已得到P,那么C,A是否可以兼得。
我們可以分情討論:
- 如果只存在一個副本
這種情況我們顯然可以得到C,但是如果集群中某些機器宕機,肯定不能得到A。
2. 如果集群中有多個副本
假設變量x=2存儲在機器A,B上。某一時刻我們把機器A上的變量x更新為1。如果此時機器A,B之間的網絡分區不可達,不能即使地將機器B也更新為1.我們不得不在A,C之間做權衡。如果選擇A,那么此時x的值處於不一致狀態;如果選擇C,那么此時應該拒絕對機器B中x值的讀請求。所以無論選擇哪一個,必將拋棄另外一個。
CAP重新解讀
- P出現的概率很小,不應該為了P在一開始就放棄C,A。
- 在設計之初應該為了同時滿足CA而努力,如果出現網絡分區,應該使系統進入P模式,進行取舍不一致狀態提供服務,當網絡分區現象結束,重新進入CA提供服務。
ACID原則
數據庫中的基礎理論。
這里的C也代表一致性,但是和分布式系統的一致性上不一樣的。
BASE原則
關系數據庫采用ACID,獲得了強一致和高可用。然而在雲存儲系統中采用BASE原則。具體而言,BASE原則是指:
- B(Basically Available):大多數時間保證可用,偶爾失敗
- S(Soft State):指數據狀態不要求任何時候都保證完全同步,處於有狀態(State)和無狀態(Stateless)之間
- 最終一致性(Eventual Consistency):給定時間窗口內達到一致
BASE原則上通過犧牲強一致性來滿足高可用性。目前一般的分布式系統采用的方案上在全局滿足BASE原則,局部滿足ACID。
CAP/ACID/BASE之間的關系
- CAP中的強一致性表現為在任何時候都像單副本一樣,是ACID中C的子集。
- 當出現網絡分區的時候,不可能滿足事務,因為事務的序列化需要網絡通信。
- 當出現網絡分區,應該盡可能地在每個分區執行ACID,等網絡分區借宿后恢復。
- YY一個問題,為什么關系數據庫的ACID不能兼容P:
因為事務需要序列化,不能容忍網絡分區。
冪等性
很重要的一個概念,先記住吧:
調用方反復調用某個操作和一次調用某個操作的結果相同。
一致性模型分類
強一致性:如果某進程對數據進行了更新,所有進程的后續操作都以這個進程為基准。更新過程中可能會出現不一致的狀態。
最終一致性:需要一段時間后才能達到強一致狀態,這段事件稱為不一致窗口。
因果一致性:
讀你所寫一致性:因果一致性的特例,相當於Notify(A, A),自己通知自己。
會話一致性:讀你所寫一致性的特例,相當於在同一個會話內保證讀你所寫一致性,但是不同的會話不保證。
單調讀一致性:保證讀操作的序列化
單調寫一致性:保證寫操作的序列化
一般滿足讀你所寫一致性和單調寫一致性
副本更新策略
分為同時更新,主從更新,任意節點更新
同時更新
- 不使用一致性協議:缺點,可能存在不一致狀態;優點:速度快
- 使用一致性協議:缺點:一致性協議延時高;優點:保證一致性
主從更新
- 同步方式:主副本等所有副副本更新完成后才確認。
- 異步方式:主副本在通知副副本之前即可確認。分為兩種情況
- 所有讀請求都通過主副本來響應,對副副本的請求會轉到主副本,這樣可以保證強一致性。
- 任意副本響應,可能出現不一致。
- 混合方式:同步更新部分節點,然后異步更新剩余節點。
- 如果讀請求必須從同步節點響應,強一致性
- 如果可以從異步節點響應,不一致狀態
任意節點更新
數據請求先發給任意副本,再由這一副本同步
- 同步方式:同主從更新同步方式
- 異步方式:同主從更新異步模式
一致性協議
2PC(兩階段提交)
兩階段提交通常用於保證數據更新的原子性。由一個協調者和眾多參與者組成
- 協調階段:
- 協調者視角:協調者向所有參與者提交一個VOTE_REQUEST消息
- 參與者視角:當參與者收到VOTE_REQUEST,參與者預先自身執行一遍事務(不提交),根據自身是否成功回應參與者
- 提交階段
- 協調者視角:如果所有參與者同意,那么向所有參與者發送提交請求;如果任意一個參與者不同意提交,參與者向所有協調者發送取消事務
- 參與者視角:如果收到GLOBAL_COMMIT,那么提交事務;如果受到GLOBAL_ABORT,取消本次事務
優點:原理簡單,實現方便
缺點:同步阻塞,單點問題,腦裂,太過保守
- 同步阻塞:兩階段提交是一個阻塞協議
- 單點問題:協調者是單點,如果在提交階段協調者宕機,參與者不能明確知道此時是否應該提交事務。
- 數據不一致:在提交階段,可能出現數據不一致
- 太過保守:沒有容錯,任何一個節點失敗導致整個事務的失敗
3PC(三階段提交)
核心思想是將協調階段一份為二
階段一:CanCommit
- 協調者:向各個參與者發送CanCommit請求
- 參與者:接受來自協調者的CanCommit請求,如果認為(應該不會預先執行)可以執行,返回yes,否則返回no
階段二:PreCommit
- 如果所有參與者返回yes
- 協調者:向所有參與者發送PreCommit
- 參與者:收到PreCommit,參與者預先執行一遍事務(不提交),根據自身是否成功返回協調者
- 如果有參與者返回no
- 參與者:發送abort請求
- 協調者:收到abort或者等待超時,都終止事務
階段三:doCommit
- 上一階段都反饋yes
- 協調者:發送提交請求,等待所有ACK,然后提交事務
- 參與者:接受到協調者的請求,提交事務。完成事務后發送ACK。
- 上階段有參與者反饋no,或者等待超時
- 協調者:發送abort
- 參與者:收到abort,終止提交;超時,提交
自己的理解:
向量時鍾
向量時鍾只有一個原則,發送,接受,進程內部事件,在當前進程的下標上加1。用於判斷時間發生的先后順序,不能完全判斷所有事件。
RWN協議
- N:在分布式系統中,有多少備份數據
- R:代表一次成功讀,至少有R份才算成功
- W:代表一次成功寫,至少有W份才算成功
如果 R + W > N,這樣肯定能保證數據的強一致性。可以根據不同的需求,配置R,W,N
paxos協議
首先介紹副本狀態機模型
一致性協議的作用就是保證各個Log副本數據的一致性,即所有服務器的內部狀態保持一致,那么這種方式使得整個集群對於外部客戶端就像單機一樣。
paxos基本概念
- 倡議者(Proposer):倡議者可以提出提議以供投票表決。
- 接受者(Acceptor):接受者可以對倡議者提出的提議進行投票表決,從眾多提議選出唯一的那個。
- 學習者(Learner):學習者無投票權,但可以從接受者獲得哪個提議被選中。
- 獲取一個ProposalId,為了保證ProposalId遞增,可以采用時間戳+serverId方式生成(我覺得這樣生成id不保證可靠);
- 提議者向所有節點廣播prepare(n)請求;
- 接收者比較n和minProposal,如果n>minProposal,表示有更新的提議,minProposal=n;否則將(acceptedProposal,acceptedValue)返回;
- 提議者接收到過半數請求后,如果發現有acceptedValue返回,表示有更新的提議,保存acceptedValue到本地,然后跳轉1,生成一個更高的提議;
- 到這里表示在當前paxos instance內,沒有優先級更高的提議,可以進入第二階段,廣播accept(n,value)到所有節點;
- 接收者比較n和minProposal,如果n>=minProposal,則acceptedProposal=minProposal=n,acceptedValue=value,本地持久化后,返回;否則,返回minProposal
- 提議者接收到過半數請求后,如果發現有返回值>n,表示有更新的提議,跳轉1;否則value達成一致。
- 另外一種表述
階段一
- 提議者:發起Prepare(n)
- 接受者:
- if(n > all Prepare) return n;
- if(n < all Prepare) 無響應;
- 接受者已經Aceept,返回{Accept編號,值}
階段二(提議者接受大多數有關提議編號n的回復):
- 提議者:發起Accept(提議編號n,提議值v)
- v選擇已經Accept中編號最高的n的提議值,否則v任意
- 接受者:
- if(n >= all Prepare) 接受,返回n
- if(n < all Prepare) 返回最大提議編號
注意:
- 在提議階段,接受者可能已經Accept
- 在接受階段,接受者可能收到新提議
- 日志內容讀取,也需要再走一遍basic paxos協議(因為paxos協議並不保證原子性,防止讀到未提交的日志?)
Multi Paxos 協議
一個Basic Paxos運行完,通過多次協議交互,只能對一件事情達到一致。因此,為了加快達成一致的速度,multi-paxos協議通過選舉出一個leader,只能由leader發起提議,這樣跳過了第一階段。Leader宕機重新選出Leader
raft
同樣基於大多數投票的選舉算法。它可以發起一系列日志,所以它對標的是multi-paxos。它將一致性協議分成幾個關鍵模塊,例如,領導人選舉、日志復制和安全性。
安全性保證:
- 只有包含所有已提交操作的命令的服務器才有權選舉為行的領導者
- 只有它自己提交當前term的操作才能看作是真正的提交。(leader只有提交了當前term號的日志后才能將之前的日志應用到狀態機)