- 一致性定義 -算法
提到一致性這個詞,你們會想到外文中有幾個單詞,如CAP中的Consistency、Cache Coherence、區塊鏈的Consensus。這三個單詞在外文不一樣環境擁有不一樣的含義。但在漢字中統一能夠翻譯爲「一致性」。所以在談一致性以前,有必要對這幾個概念作一個區分,不然很容易讓人迷惑。緩存
-
Coherence:出如今Cache Coherence 一詞中,稱爲「緩存一致性」。微信
-
Consensus:準確翻譯是共識,即多個提議者達成共識的過程,例如Paxos、Raft 就是共識算法,是一種共識理論,分佈式系統是它的場景,一致性是它的目標。網絡
-
Consistency:一致性,即在分佈式系統中的全部數據備份在同一時刻的值是否相同。架構
一些常見的誤解:app
-
一致性等於共識?其實一致性比共識含義更寬泛,一致性指的是多個副本對外呈現的狀態。包括線性一致性、順序一致性、最終一致性等。而共識特指達成一致的過程,但注意,共識並不意味着實現了一致性,一些狀況下它是作不到的。分佈式
-
使用了 Raft 或者 Paxos 的系統都是線性一致的(Linearizability)嗎?其實否則,共識算法只能提供基礎,要實現線性一致還須要在算法之上作出更多努力。oop
由於分佈式系統引入了多個節點,節點規模越大,宕機、網絡時延、網絡分區就越會成爲常態,任何一個問題均可能致使節點之間的數據不一致。Paxos 和 Raft 共識算法初始被提出來是爲了在分佈式場景下處理數據同步問題。由於分佈式一致性的範圍更大,且Paxos、Raft只需引入一些小改動就能夠達到線性一致性,因此被擴展引伸爲「Paxos、Raft是分佈式系統中的一致性算法」。性能
- 一致性分類 -區塊鏈
強一致性和弱一致性只是一種統稱,按照從強到弱,能夠劃分爲:-
線性一致性 Linearizability consistency
定義:任何操做均可能在調用或者返回之間原子和瞬間執行,也稱爲原子一致性(atomic consistency),是標準的強一致性(strong consistency)。簡而言之,在任意時刻,保證對外提供的數據是同樣的。主要實現的算法有 Paxos、Raft、PacificA 等,它們都達到如下要求:
-
任何一次讀都能讀到某個數據的最近一次寫的數據。
-
系統中的全部進程,看到的操做順序,都和全局時鐘下的順序一致。
-
-
順序一致性 Sequential consistency
定義:程序的執行順序和它編寫的順序一致。由於讀的操做一般不改變數據,因此一般咱們也認爲它算一種強一致實現,主要實現的算法有ZAB協議。它的特色有:
-
一個線程中的全部操做必須按照程序的順序來執行。
-
無論程序是否同步,全部線程都只能看到一個單一的操做執行順序。在順序一致性內存模型中,每一個操做都必須原子執行且馬上對全部線程可見。
-
-
因果一致性 Causal consistency
定義:全部進程必須以相同的順序看到具備潛在因果關係的寫操做。即只有存在因果關係的寫操做纔要求全部使用者以相同的次序看到,對於無因果關係的寫入則並行進行,無次序保證。因果一致性能夠看做對順序一致性性能的一種優化。
-
管道一致性 PRAM/FIFO consistency
定義:所某一個使用者完成的寫操做能夠被其餘全部的使用者按照順序的感知到,而從不一樣使用者中來的寫操做則無需保證順序,就像一個一個的管道同樣。一般咱們認爲它算是一種弱一致性。
-
最終一致性 Eventual consistency
定義:存儲系統保證若是沒有新的更新提交,最終全部的訪問都將得到最後的更新。主要實現算法有Gossip協議等,根據更新數據後各進程訪問到數據的時間和方式的不一樣,又能夠區分爲:
-
讀不舊於寫一致性 Read-your-writes Consistency :使用者讀到的數據,老是不舊於自身上一個寫入的數據。
-
會話一致性:對系統數據的訪問過程框定在了一個會話當中,系統可以保證在同一個有效的會話中實現「讀己之所寫」的一致性,也就是說,執行更新操做以後,客戶端可以在同一個會話中始終讀取到該數據項的最新值。
-
單調讀一致性 Monotonic-read Consistency :若是一個進程從系統中讀取出一個數據項的某個值後,那麼系統對於該進程後續的任何數據訪問都不該該返回更舊的值。
-
單調寫一致性 Monotonic-write Consistency :一個系統須要可以保證來自同一個進程的寫操做被順序地執行。
-
寫不舊於讀一致性 Writes-follow-reads Consistency :寫入的副本不舊於上一次讀到的數據,即不會寫入更舊的數據。
-
因果一致性由於實現很是困難,因此一般咱們不承認這個分類。同理還有不少其餘的弱一致性實現不具有太大的意義,也被排除釋放一致性(Release Consistency)、滑動不一致(Delta Consistency)。
- 線性一致性 -
線性一致性是強一致性的標準實現,線性一致性分爲:線性一致性寫、線性一致性讀。
線性一致性寫
全部的 write 都會來到 Leader,write 會有 Op log Leader 被序列化,依次順序日後 commit,並 apply 而後在返回,那麼一旦一個 write 被 committed,那麼其前面的 write 的 Op log 必定就被 committed 了,保證日誌完整性。全部的 write 都是有嚴格的順序的,一旦被 committed 就可見了。簡而言之, 線性一致性寫,就是Leader write + 過半寫入 ,Raft、Paxos、ZAB都是這樣實現的。
線性一致性讀
線性一致性讀的實現有不少方式,在Raft中,read 有多種實現:
-
Raft log Read:每一個 read 都有一個對應的 Op log,和 write 同樣,都會走一遍一致性協議的流程,會在此 Read Op log 被 Apply 的時候讀,那麼這個 read Op log 以前的 write Op log 確定也被 applied 了,那麼必定可以被讀取到,讀到的也必定是最新的。
-
ReadIndex:咱們知道 Raft log read,會有 raft read log 的複製和提交的開銷,因此出現了 ReadIndex,read 沒有 Op log,可是須要額外的機制保證讀到最新的,因此 read 發送給 Leader 的時候,
-
它須要確認 read 返回的數據的那個點 ?必須返回最新 committed 的結果,可是一個節點剛當選 Leader 的時候並不知道最新的 committed index,這個時候須要提交一個 Noop log entry 來提交以前的 log entry,而後開始 Read;
-
它須要確認當前的 Leader 是否是仍是 Leader,由於可能由於網絡分區,這個 Leader 已經被孤立了,因此 Leader 在返回 read 以前,先和 Replica-group 的其餘成員發送 heartbeat 肯定本身 Leader 的身份。經過上述兩條保證讀到最新被 committed 的數據。
-
-
Lease Read:主要是經過 lease 機制維護 Leader 的狀態,來減小了 ReadIndex 每次 read 發送 heartheat 的開銷。每次Follower進行讀請求時,Leader只須要判斷本身的Leader租約是否過時了,若是沒有過時,直接能夠回覆Follower本身是Leader,可是該機制對於機器時鐘要求很嚴格,若是有作時鐘同步的話,能夠考慮使用該線性讀模式。
-
Follower Read:先去 Leader 查詢最新的 committed index,而後拿着 committed Index 去 Follower read,從而保證能從 Follower 中讀到最新的數據,當前 etcd 就實現了 Follower read。
- 總結 -
我們總體介紹了一致性與共識的差異、一致性的分類,線性一致性的實現方案分類。總結以下:-
共識是一種數據同步過程,一致性是數據同步狀態。因此一致性算法含義更普遍,包含了共識。
-
強一致性分線性一致性、順序一致性,根據場景能夠選擇合適的一致性算法。
-
弱一致性由於實現成本和場景意義問題,咱們一般認爲弱一致性就是最終一致性。
- 做者介紹 -
林淮川
畢業於西安交通大學;奈學教育《百萬架構師訓練營》講師、企業級源碼內源負責人,前大樹金融高級架構師、技術委員會開創者、技術總監;前天陽宏業交易事業部技術主管;多年互聯網金融行業(ToB)經驗。
本文分享自微信公衆號 - 川聊架構(gh_44ec4115d261)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。