Quorum NWR算法

假如我們遇到這樣一種事情:你開發實現了一套 AP 型的分佈式系統,實現了最終一致性。業務也接入了,運行正常,一起看起來都那麼美好。可是,突然有同事說,我們要拉這幾個業務的數據做實時分析,希望數據寫入成功後,就能立即讀取到新數據,也就是要實現強一致性,數據更改後,要保證用戶能立即查詢到。這時你該怎麼辦呢?首先你要明確最終一致性強一致性有什麼區別。

強一致性能保證寫操作完成後,任何後續訪問都能讀到更新後的值;最終一致性只能保證如果對某個對象沒有新的寫操作了,最終所有後續訪問都能讀到相同的最近更新的值。也就是說,寫操作完成後,後續訪問可能會讀到舊數據。

其實,爲了一個臨時的需求,我們重新開發一套系統,或者遷移數據到新系統,肯定是不合適的。因爲工作量比較大,而且耗時也長,而我建議你通過 Quorum NWR 解決這個問題。

也就是說,在原有系統上開發實現一個新功能,就可以滿足業務同學的需求了。因爲通過Quorum NWR,你可以自定義一致性級別,通過臨時調整寫入或者查詢的方式,當 W +R > N 時,就可以實現強一致性了。

其實,在 AP 型分佈式系統中(比如 Dynamo、Cassandra、InfluxDB 企業版的 DATA 節點集羣),Quorum NWR 是通常都會實現的一個功能,很常用。對你來說,掌握Quorum NWR,不僅是掌握一種常用的實現一致性的方法,更重要的是,後續用戶可以根據業務的特點,靈活地指定一致性級別。

爲了掌握 Quorum NWR,除了瞭解它的原理外,我們還會以 InfluxDB 企業版的實現爲例,帶你看一下它在實際場景中的實現,這樣你可以在理解原理的基礎上,掌握Quorum NWR 的實戰技巧。

首先,需要了解 Quorum NWR 中的三個要素,N、W、R。因爲它們是 Quorum NWR的核心內容,我們就是通過組合這三個要素,實現自定義一致性級別的。

Quorum NWR 的三要素

N 表示副本數,又叫做複製因子(Replication Factor)。也就是說,N 表示集羣中同一份數據有多少個副本,就像下圖的樣子:

在這裏插入圖片描述

從圖中你可以看到,在這個三節點的集羣中,DATA-1 有 2 個副本,DATA-2 有 3 個副本,DATA-3 有 1 個副本。也就是說,副本數可以不等於節點數,不同的數據可以有不同的副本數。

需要你注意的是,在實現 Quorum NWR 的時候,你需要實現自定義副本的功能。也就是說,用戶可以自定義指定數據的副本數,比如,用戶可以指定 DATA-1 具有 2 個副本,DATA-2 具有 3 個副本,就像圖中的樣子。

當我們指定了副本後,就可以對副本數據進行讀寫操作了。那麼這麼多副本,你要如何執行讀寫操作呢?先來看一看寫操作,也就是 W。

W,又稱寫一致性級別(Write Consistency Level),表示成功完成 W 個副本更新,才完成寫操作:
在這裏插入圖片描述

從圖中你可以看到,DATA-2 的寫副本數爲 2,也就說,對 DATA-2 執行寫操作時,完成了 2 個副本的更新(比如節點 A、C),才完成寫操作。那麼有的同學會問了,DATA-2 有 3 個數據副本,完成了 2 副本的更新,就完成了寫操作,那麼如何實現強一致性呢?如果讀到了第三個數據副本(比如節點 B),不就可能無法讀到更新後的值了嗎?別急,我講完如何執行讀操作後,你就明白了。

R,又稱讀一致性級別(Read Consistency Level),表示讀取一個數據對象時需要讀 R個副本。你可以這麼理解,讀取指定數據時,要讀 R 副本,然後返回 R 個副本中最新的那份數據:

在這裏插入圖片描述

從圖中你可以看到,DATA-2 的讀副本數爲 2。也就是說,客戶端讀取 DATA-2 的數據時,需要讀取 2 個副本中的數據,然後返回最新的那份數據。

這裏需要注意的是,無論客戶端如何執行讀操作,哪怕它訪問的是寫操作未強制更新副本數據的節點(比如節點 B),但因爲 W(2) + R(2) > N(3),也就是說,訪問節點 B,執行讀操作時,因爲要讀 2 份數據副本,所以除了節點 B 上的 DATA-2,還會讀取節點 A 或節點 C 上的 DATA-2,就像上圖的樣子(比如節點 C 上的 DATA-2),而節點 A 和節點 C的 DATA-2 數據副本是強制更新成功的。這個時候,返回給客戶端肯定是最新的那份數據。

你看,通過設置 R 爲 2,即使讀到前面問題中的第三份副本數據(比如節點 B),也能返回更新後的那份數據,實現強一致性了。

除此之外,關於 NWR 需要你注意的是,N、W、R 值的不同組合,會產生不同的一致性效果,具體來說,有這麼兩種效果:

  • 當 W + R > N 的時候,對於客戶端來講,整個系統能保證強一致性,一定能返回更新後的那份數據。
  • 當 W + R < N 的時候,對於客戶端來講,整個系統只能保證最終一致性,可能會返回舊數據。

你可以看到,Quorum NWR 的原理並不複雜,也相對比較容易理解,但在這裏,我想強調一下,掌握它的關鍵在於如何根據不同的場景特點靈活地實現 Quorum NWR,所以接下來,我帶你具體問題具體分析,以 InfluxDB 企業版爲例講解一下。

如何實現 Quorum NWR?

在 InfluxDB 企業版中,可以在創建保留策略時,設置指定數據庫(Database)對應的副本數,具體的命令,就像下面的樣子:

create retention policy “rp_one_day” on “telegraf” duration 1d replication 3

通過 replication 參數,指定了數據庫 telegraf 對應的副本數爲 3。

需要你注意的,在 InfluxDB 企業版中,副本數不能超過節點數據。你可以這麼理解,多副本的意義在於冗餘備份,如果副本數超過節點數,就意味着在一個節點上會存在多個副本,那麼這時冗餘備份的意義就不大了。比如機器故障時,節點上的多個副本是同時被影響的。InfluxDB 企業版,支持“any、one、quorum、all”4 種寫一致性級別,具體的含義是這樣的。

  • any:任何一個節點寫入成功後,或者接收節點已將數據寫入 Hinted-handoff 緩存(也就是寫其他節點失敗後,本地節點上緩存寫失敗數據的隊列)後,就會返回成功給客戶端。
  • one:任何一個節點寫入成功後,立即返回成功給客戶端,不包括成功寫入到 Hinted-handoff 緩存。
  • quorum:當大多數節點寫入成功後,就會返回成功給客戶端。此選項僅在副本數大於 2 時纔有意義,否則等效於 all。
  • all:僅在所有節點都寫入成功後,返回成功。

我想強調一下,對時序數據庫而言,讀操作常會拉取大量數據,查詢性能是挑戰,是必須要考慮優化的,因此,在 InfluxDB 企業版中,不支持讀一致性級別,只支持寫一致性級別。另外,我們可以通過設置寫一致性級別爲 all,來實現強一致性。

你看,如果我們像 InfluxDB 企業版這樣,實現了 Quorum NWR,那麼在業務臨時需要實現強一致性時,就可以通過設置寫一致性級別爲 all,來實現了。

小結

一般而言,不推薦副本數超過當前的節點數,因爲當副本數據超過節點數時,就會出現
同一個節點存在多個副本的情況。當這個節點故障時,上面的多個副本就都受到影響
了。

  • 當 W + R > N 時,可以實現強一致性。另外,如何設置 N、W、R 值,取決於我們想化哪方面的性能。比如,N 決定了副本的冗餘備份能力;
  • 如果設置 W = N,讀性能比較好;如果設置 R = N,寫性能比較好;
  • 如果設置 W = (N + 1) / 2、R = (N + 1) / 2,容錯能力比較好,能容忍少數節點(也就是 (N - 1) / 2)的故障。

最後,我想說的是,Quorum NWR 是非常實用的一個算法,能有效彌補 AP 型系統缺乏強
一致性的痛點,給業務提供了按需選擇一致性級別的靈活度,建議你的開發實現 AP 型系統
時,也實現 Quorum NWR。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章