「太白金星:聽聞老君最近在練神丹妙藥,能否與我一講?web
太上老君:老白啊,我最近在練六顆丹藥:兩顆
延年丹
、兩顆健步丹
、兩顆恢復丹
。算法太白金星:那這三個八卦爐定是練這三件法寶的?數據庫
太上老君:正是正是。並且對於相同的丹藥,功效和大小還得徹底同樣。小程序
」
1、三個煉丹爐怎麼分配的
「太白金星:老君,你的八卦爐怎麼分配的啊?數組
」
讓咱們揭開老君的煉丹爐,看看六顆丹藥是怎麼分配的。瀏覽器
首先咱們是很容易猜到丹爐是怎麼分配煉丹的:緩存
-
一號丹爐煉兩顆 延年丹
。 -
二號丹爐煉兩顆 健步丹
。 -
三號丹爐煉兩顆 恢復丹
。
那如此分配會有什麼問題呢?性能優化
咱們試想一下,若是一號丹爐由於爐火過高炸裂了,那麼兩顆延年丹定會失敗。這和把雞蛋放到一個籃子裏面是一個道理。假如籃子不慎被打翻,裏面的雞蛋都掉出來,就都碎了。服務器
「太上老君:老白,我把鍋爐的蓋子揭開給你看看你就知道了。微信
」
-
一號丹爐煉一顆 延年丹
和一顆健步丹
。 -
二號丹爐煉一顆 延年丹
和一顆恢復丹
。 -
三號丹爐煉一顆 健步丹
和一顆恢復丹
。
「太白金星:老君,爲什麼要如此分配,每一個丹藥的火候可不那麼好把控啊?
太上老君:老白,我但是煉丹大師,火候難不倒我。
太白金星:不愧是老君啊,這樣即便有一個丹爐有問題,至少能保證一顆能煉成,而不是兩顆都毀了。
」
映射到咱們互聯網系統中:丹爐相似於服務器節點或數據庫節點,經過多個節點來相互備份數據來保證系統的高可用性
(High Availability)。
2、如何保證丹藥品質同樣
2.1 一致性
「太白金星:老君,你剛提到,兩顆延年丹須要保證功效同樣,大小同樣?
太上老君:確實如此,丹藥品質必須保持一致,我煉的都是九品丹藥,藥效差一點則是千差萬別。
」
太上老君說的品質保持一致到底怎麼回事?
一號丹爐裏面的延年丹和二號丹爐的延年丹如何保證品質一致呢?
這不就是咱們經常說的分佈式一致性
嗎?兩顆丹藥分佈在不一樣的丹爐中,須要保證品質一致。
以下圖所示,這兩顆延年丹的一大一小,顏色也有不一樣,這就是品質不同。
而在架構設計中,好比請求訪問到不一樣的數據庫,查到的數據都是同樣的,這就是一致性。
以下圖所示:瀏覽器訪問數據庫 1 和數據庫 2 中的數據 A,結果返回的都是 A = 1。
2.2 最終一致性和強一致性
分佈式中的一致性又分爲最終一致性
和強一致性
。
所謂強一致性
就是寫操做完成後,任何後續訪問都能讀到更新後的值。這就是CP
系統所要求的一致性和分區容錯性。。
那放到煉丹中怎麼理解?
好比老君給一號丹爐的延年丹加入了蓮花
這種藥材,給二號丹爐的延年丹也這麼操做,那麼老白揭開爐蓋看到的兩顆延年丹的成分是同樣的。
而最終一致性
就是不保證後續訪問都能讀到更新後的值,可是通過一段時間後,再去讀,就能獲得相同的值。也就是說,在這段時間內,可能讀到舊的數據。這就是AP
系統所要求的可用性和分區容錯性。
放到煉丹中怎麼理解?
好比老君給一號丹爐的延年丹加入了蓮花,而通過了一個時辰後,纔給二號丹爐加雪蓮,那麼在這個時辰內,看到的兩顆延年丹的成分就不同了。但通過一個時辰後,最終成分同樣。
3、可控的品質:Quorum NWR 協議
「假如延年丹必須保證品質的強一致性,而健步丹只須要保證品質的最終一致性,這個該怎麼控制呢?
」
這個可沒有難倒老君,由於老君懂得分佈式協議:Quorum NWR
。
Quorum 這個單詞的意思:(會議的)法定人數。主要是看後面三個大寫字母:N
、W
、R
。由 NWR 來控制一致性。
3.1 參數 N
咱們仍是來看下丹爐中的狀況,兩顆延年丹是互爲備份的,至關於有兩個副本。
N 稱做副本數,又叫作複製因子(Replication Factor)。表示同一份數據有多少個副本,因此:延年丹的 N = 2。依次類推:健步丹的 N = 2,恢復丹的 N = 2。以下圖所示:
那 N 能夠變嗎?
以下圖所示:好比我想煉 3 顆延年丹,也就是每一個丹爐都有延年丹,那就把 N 改爲 3 就能夠了。而健步丹只須要煉一顆足以,那一號丹爐煉就能夠了,因此N = 1。
3.2 參數 W
指定了副本數 N 以後,就能夠對副本數據進行讀寫操做。
-
讀操做:查看所在丹爐內丹藥的狀況。 -
寫操做:給丹藥添加藥材、提升溫度。
那多個丹藥該如何執行讀寫操做呢?對於寫操做,咱們有 W 參數,對於讀操做,咱們有 R 參數。
W 稱爲寫一致性級別(Write Consistency Level),表示成功完成 W 個副本更新,才完成寫操做。
好比設置延年丹的 W = 2,表示對延年丹執行寫操做時,完成了 2 個副本的更新時,才完成寫操做。
以下圖所示:一號丹爐和二號丹爐中的延年丹都加入了蓮花,而三號丹爐中的延年丹未加入蓮花。也就是隻完成了兩個副本的更新,符合 W = 2 這個條件,即寫操做完成。
可是你們發現問題沒,三號丹爐的延年丹未加入蓮花,那怎麼保證太上老君查看丹藥狀況時,得知是已加入蓮花呢?也就是如何保證讀寫的強一致性,這就要用到第三個參數了:R。
3.3 參數 R
R 稱爲讀一致性級別(Read Consistency Level),表示讀取一個數據對象時,須要讀 R 個副本,而後返回 R 個副本中最新的那份數據。
回到煉丹的問題中,設置延年丹的 R = 2,也就是查看延年丹的狀況時,只須要查看兩個丹爐內的延年丹的狀況,而後返回最新的延年丹的狀況就能夠了。
-
假設查看的是一號和二號丹爐內的延年丹,返回的狀況都是:已加入蓮花。這種場景是一致性的。
-
假設查看的是一號和三號丹爐內的延年丹,一號丹爐的延年丹是已加入蓮花,三號丹爐是未加入蓮花,可是三號丹爐內的延年丹最後一次操做時間是早於一號丹爐的,因此返回一號丹爐內延年丹的狀況:已加入蓮花。這種場景也是一致性的。
經過上面的兩種場景,咱們知道,經過設置 R = 2,即便讀到第三份未更新的數據,也能返回更新後的數據,實現強一致性。
3.4 參數組合
參數 N、W、R 的不一樣組合將會帶來不一樣的一致性效果。
-
好比上面的例子,N = 3,W = 2,R = 2,W + R > N,對於客戶端來說,整個系統能保證強一致性,必定能返回更新後的那份數據。
-
當 W + R <= N 時,對於客戶端來說,整個系統只能保證最終一致性,訪問數據期間可能會返回舊數據。
參數不一樣,效果不一樣,分佈式系統須要根據不一樣場景來配置。
4、應用
InfluxDB 企業版是時序數據庫,它有四種寫一致性級別:
-
any:W + R < N,W = 1,任何一個節點寫入成功後,或者寫入 Hinted-handoff 緩存(等下次重傳),返回成功給客戶端。 -
one:W + R < N,W = 1,任何一個節點寫入成功後,當即返回成功給客戶端,不包括寫入 Hinted-handoff 緩存 -
quorum:W + R > N,大多數節點寫入成功後,就返回成功給客戶端。(要求 N 大於2) -
all:W = N,全部節點都寫入成功後,返回成功。
另外對於 時序數據庫 InfluxDB 來講,讀操做須要讀取大量數據,爲了保證讀取的高效,它不支持讀一致性級別(R = N),可是能夠經過設置寫一致性級別爲 all,來實現強一致性。
InfluxDb 實現了 Quorum NWR,當線上業務須要臨時作些一致性調整時,設置不一樣的寫一致性級別便可完成快速切換。
5、總結
本文經過太上老君和太白金星關於煉丹的對話,引伸出自定義一致性的分佈式協議:Quorum NWR 協議。
丹爐比喻節點,丹藥比做數據,多個丹藥稱做副本。
-
N 表明副本數,W 表明寫多少個副本數,R 表明讀多少個副本數。
-
當 N 大於節點數時,就會出現一個節點存在多個副本的狀況,這個節點故障時,多個副本會受到影響。
-
W + R > N 時,表明強一致性。
-
W = N 時,讀性能好。R = N,寫性能好。
-
W = R = (N+1)/2,容錯能力好,能容忍 少數節點(也就是(N-1)/2) 個節點故障。
-
如何設置 N、W、R 值,取決於咱們的系統該往哪方面優化。
-
Quorum NWR 分佈式算法給業務提供了按需選擇一致性級別的靈活度,彌補了 AP 型系統缺少強一致性的缺點。
「太白金星:預祝你煉丹成功!我要去分享和留言了!
」
- END -
做者簡介:悟空,8年一線互聯網開發和架構經驗,用故事講解分佈式、架構設計。《JVM性能優化實戰》專欄做者,開源了《Spring Cloud 實戰 PassJava》項目,自主開發了一個 PMP 刷題小程序。關注可免費刷題。
本文分享自微信公衆號 - 悟空聊架構(PassJava666)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。