太上老君的煉丹爐之分布式 Quorum NWR
“太白金星:聽聞老君最近在練神丹妙藥,可否與我一講?
太上老君:老白啊,我最近在練六顆丹藥:兩顆延年丹、兩顆健步丹、兩顆恢復(fù)丹。
太白金星:那這三個八卦爐定是練這三件法寶的?
太上老君:正是正是。而且對于相同的丹藥,功效和大小還得完全一樣。”
三種丹藥
一、三個煉丹爐怎么分配的“
太白金星:老君,你的八卦爐怎么分配的啊?
”讓我們揭開老君的煉丹爐,看看六顆丹藥是怎么分配的。
首先我們是很容易猜到丹爐是怎么分配煉丹的:
- 一號丹爐煉兩顆延年丹。
- 二號丹爐煉兩顆健步丹。
- 三號丹爐煉兩顆恢復(fù)丹。
太白金星認(rèn)為的丹爐情況
那如此分配會有什么問題呢?
我們試想一下,如果一號丹爐因?yàn)闋t火太高炸裂了,那么兩顆延年丹定會失敗。這和把雞蛋放到一個籃子里面是一個道理。假如籃子不慎被打翻,里面的雞蛋都掉出來,就都碎了。
“太上老君:老白,我把鍋爐的蓋子揭開給你看看你就知道了。”
- 一號丹爐煉一顆延年丹和一顆健步丹。
- 二號丹爐煉一顆延年丹和一顆恢復(fù)丹。
- 三號丹爐煉一顆健步丹和一顆恢復(fù)丹。
丹爐實(shí)際分配情況
“太白金星:老君,為何要如此分配,每個丹藥的火候可不那么好把控啊?
太上老君:老白,我可是煉丹大師,火候難不倒我。
太白金星:不愧是老君啊,這樣即使有一個丹爐有問題,至少能保證一顆能煉成,而不是兩顆都?xì)Я恕?rdquo;
映射到我們互聯(lián)網(wǎng)系統(tǒng)中:丹爐類似于服務(wù)器節(jié)點(diǎn)或數(shù)據(jù)庫節(jié)點(diǎn),通過多個節(jié)點(diǎn)來相互備份數(shù)據(jù)來保證系統(tǒng)的高可用性(High Availability)。
二、如何保證丹藥品質(zhì)一樣
2.1 一致性
“太白金星:老君,你剛提到,兩顆延年丹需要保證功效一樣,大小一樣?
太上老君:確實(shí)如此,丹藥品質(zhì)必須保持一致,我煉的都是九品丹藥,藥效差一點(diǎn)則是千差萬別。”
太上老君說的品質(zhì)保持一致到底怎么回事?
一號丹爐里面的延年丹和二號丹爐的延年丹如何保證品質(zhì)一致呢?
這不就是我們常常說的分布式一致性嗎?兩顆丹藥分布在不同的丹爐中,需要保證品質(zhì)一致。
如下圖所示,這兩顆延年丹的一大一小,顏色也有不同,這就是品質(zhì)不一樣。
品質(zhì)不一樣
而在架構(gòu)設(shè)計(jì)中,比如請求訪問到不同的數(shù)據(jù)庫,查到的數(shù)據(jù)都是一樣的,這就是一致性。
如下圖所示:瀏覽器訪問數(shù)據(jù)庫 1 和數(shù)據(jù)庫 2 中的數(shù)據(jù) A,結(jié)果返回的都是 A = 1。
分布式系統(tǒng)中的一致性
2.2 最終一致性和強(qiáng)一致性
分布式中的一致性又分為最終一致性和強(qiáng)一致性。
所謂強(qiáng)一致性就是寫操作完成后,任何后續(xù)訪問都能讀到更新后的值。這就是CP系統(tǒng)所要求的一致性和分區(qū)容錯性。。
那放到煉丹中怎么理解?
比如老君給一號丹爐的延年丹加入了蓮花這種藥材,給二號丹爐的延年丹也這么操作,那么老白揭開爐蓋看到的兩顆延年丹的成分是一樣的。
而最終一致性就是不保證后續(xù)訪問都能讀到更新后的值,但是經(jīng)過一段時間后,再去讀,就能得到相同的值。也就是說,在這段時間內(nèi),可能讀到舊的數(shù)據(jù)。這就是AP系統(tǒng)所要求的可用性和分區(qū)容錯性。
放到煉丹中怎么理解?
比如老君給一號丹爐的延年丹加入了蓮花,而經(jīng)過了一個時辰后,才給二號丹爐加雪蓮,那么在這個時辰內(nèi),看到的兩顆延年丹的成分就不一樣了。但經(jīng)過一個時辰后,最終成分一樣。
三、可控的品質(zhì):Quorum NWR 協(xié)議
“假如延年丹必須保證品質(zhì)的強(qiáng)一致性,而健步丹只需要保證品質(zhì)的最終一致性,這個該怎么控制呢?
”這個可沒有難倒老君,因?yàn)槔暇梅植际絽f(xié)議:Quorum NWR。
Quorum 這個單詞的意思:(會議的)法定人數(shù)。主要是看后面三個大寫字母:N、W、R。由 NWR 來控制一致性。
3.1 參數(shù) N
我們還是來看下丹爐中的情況,兩顆延年丹是互為備份的,相當(dāng)于有兩個副本。
N 稱作副本數(shù),又叫做復(fù)制因子(Replication Factor)。表示同一份數(shù)據(jù)有多少個副本,所以:延年丹的 N = 2。依次類推:健步丹的 N = 2,恢復(fù)丹的 N = 2。如下圖所示:
丹藥的副本數(shù)一樣
那 N 可以變嗎?
如下圖所示:比如我想煉 3 顆延年丹,也就是每個丹爐都有延年丹,那就把 N 改成 3 就可以了。而健步丹只需要煉一顆足以,那一號丹爐煉就可以了,所以N = 1。
多個丹藥的副本數(shù)不一樣
3.2 參數(shù) W
指定了副本數(shù) N 之后,就可以對副本數(shù)據(jù)進(jìn)行讀寫操作。
- 讀操作:查看所在丹爐內(nèi)丹藥的情況。
- 寫操作:給丹藥添加藥材、提高溫度。
那多個丹藥該如何執(zhí)行讀寫操作呢?對于寫操作,我們有 W 參數(shù),對于讀操作,我們有 R 參數(shù)。
W 稱為寫一致性級別(Write Consistency Level),表示成功完成 W 個副本更新,才完成寫操作。
比如設(shè)置延年丹的 W = 2,表示對延年丹執(zhí)行寫操作時,完成了 2 個副本的更新時,才完成寫操作。
如下圖所示:一號丹爐和二號丹爐中的延年丹都加入了蓮花,而三號丹爐中的延年丹未加入蓮花。也就是只完成了兩個副本的更新,符合 W = 2 這個條件,即寫操作完成。
兩個延年丹加入了蓮花
但是大家發(fā)現(xiàn)問題沒,三號丹爐的延年丹未加入蓮花,那怎么保證太上老君查看丹藥情況時,得知是已加入蓮花呢?也就是如何保證讀寫的強(qiáng)一致性,這就要用到第三個參數(shù)了:R。
3.3 參數(shù) R
R 稱為讀一致性級別(Read Consistency Level),表示讀取一個數(shù)據(jù)對象時,需要讀 R 個副本,然后返回 R 個副本中最新的那份數(shù)據(jù)。
回到煉丹的問題中,設(shè)置延年丹的 R = 2,也就是查看延年丹的情況時,只需要查看兩個丹爐內(nèi)的延年丹的情況,然后返回最新的延年丹的情況就可以了。
- 假設(shè)查看的是一號和二號丹爐內(nèi)的延年丹,返回的情況都是:已加入蓮花。這種場景是一致性的。
- 假設(shè)查看的是一號和三號丹爐內(nèi)的延年丹,一號丹爐的延年丹是已加入蓮花,三號丹爐是未加入蓮花,但是三號丹爐內(nèi)的延年丹最后一次操作時間是早于一號丹爐的,所以返回一號丹爐內(nèi)延年丹的情況:已加入蓮花。這種場景也是一致性的。
通過上面的兩種場景,我們知道,通過設(shè)置 R = 2,即使讀到第三份未更新的數(shù)據(jù),也能返回更新后的數(shù)據(jù),實(shí)現(xiàn)強(qiáng)一致性。
3.4 參數(shù)組合
參數(shù) N、W、R 的不同組合將會帶來不同的一致性效果。
- 比如上面的例子,N = 3,W = 2,R = 2,W + R > N,對于客戶端來講,整個系統(tǒng)能保證強(qiáng)一致性,一定能返回更新后的那份數(shù)據(jù)。
- 當(dāng) W + R <= N 時,對于客戶端來講,整個系統(tǒng)只能保證最終一致性,訪問數(shù)據(jù)期間可能會返回舊數(shù)據(jù)。
參數(shù)不同,效果不同,分布式系統(tǒng)需要根據(jù)不同場景來配置。
四、應(yīng)用
InfluxDB 企業(yè)版是時序數(shù)據(jù)庫,它有四種寫一致性級別:
- any:W + R < N,W = 1,任何一個節(jié)點(diǎn)寫入成功后,或者寫入 Hinted-handoff 緩存(等下次重傳),返回成功給客戶端。
- one:W + R < N,W = 1,任何一個節(jié)點(diǎn)寫入成功后,立即返回成功給客戶端,不包括寫入 Hinted-handoff 緩存
- quorum:W + R > N,大多數(shù)節(jié)點(diǎn)寫入成功后,就返回成功給客戶端。(要求 N 大于2)
- all:W = N,所有節(jié)點(diǎn)都寫入成功后,返回成功。
另外對于 時序數(shù)據(jù)庫 InfluxDB 來說,讀操作需要讀取大量數(shù)據(jù),為了保證讀取的高效,它不支持讀一致性級別(R = N),但是可以通過設(shè)置寫一致性級別為 all,來實(shí)現(xiàn)強(qiáng)一致性。
InfluxDb 實(shí)現(xiàn)了 Quorum NWR,當(dāng)線上業(yè)務(wù)需要臨時做些一致性調(diào)整時,設(shè)置不同的寫一致性級別即可完成快速切換。
五、總結(jié)
本文通過太上老君和太白金星關(guān)于煉丹的對話,引申出自定義一致性的分布式協(xié)議:Quorum NWR 協(xié)議。
- 丹爐比喻節(jié)點(diǎn),丹藥比作數(shù)據(jù),多個丹藥稱作副本。
- N 代表副本數(shù),W 代表寫多少個副本數(shù),R 代表讀多少個副本數(shù)。
- 當(dāng) N 大于節(jié)點(diǎn)數(shù)時,就會出現(xiàn)一個節(jié)點(diǎn)存在多個副本的情況,這個節(jié)點(diǎn)故障時,多個副本會受到影響。
- W + R > N 時,代表強(qiáng)一致性。
- W = N 時,讀性能好。R = N,寫性能好。
- W = R = (N+1)/2,容錯能力好,能容忍 少數(shù)節(jié)點(diǎn)(也就是(N-1)/2) 個節(jié)點(diǎn)故障。
- 如何設(shè)置 N、W、R 值,取決于我們的系統(tǒng)該往哪方面優(yōu)化。
- Quorum NWR 分布式算法給業(yè)務(wù)提供了按需選擇一致性級別的靈活度,彌補(bǔ)了 AP 型系統(tǒng)缺乏強(qiáng)一致性的缺點(diǎn)。
本文轉(zhuǎn)載自微信公眾號「悟空聊架構(gòu)」,可以通過以下二維碼關(guān)注。轉(zhuǎn)載本文請聯(lián)系悟空聊架構(gòu)公眾號。