1.強一致性與最終一致性
1.1強一致性
強一致效能保證寫操作完成後,任何後續訪問都能讀到更新後的值;強一致性可以保證從庫有與主庫一致的資料。如果主庫突然當機,我們仍可以保證資料完整。但如果從庫當機或網路阻塞,主庫就無法完成寫入操作。
1.2最終一致性
最終一致性只能保證如果對某個物件沒有新的寫操作了,最終所有後續訪問都能讀到相同的最近更新的值。開篇提到,容忍節點故障只是需要複製的一個原因。另兩個原因是可擴充套件性和降低延遲。
單領導者的主從複製演算法要求所有寫入都由單個節點處理,但只讀查詢可以由任何節點處理。對於讀多寫少的場景,我們往往建立很多從庫,並將讀請求分散到所有的從庫上去。這樣能減小主庫的負載,並允許向最近的節點傳送讀請求。當然這隻適用於非同步複製——如果嘗試同步複製,則單個節點故障將使整個系統無法寫入。
當使用者從非同步從庫讀取時,如果此非同步從庫落後,他可能會看到過時的資訊。這種不一致只是一個暫時的狀態——如果等待一段時間,從庫最終會趕上並與主庫保持一致。這稱為最終一致性。
最終兩個字用得很微妙,因為從寫入主庫到反映至從庫之間的延遲,可能僅僅是幾分之一秒,也可能是幾個小時。
2.Quorum NWR 的三要素
2.1副本數
N 表示副本數,又叫做複製因子(Replication Factor)。也就是說,N 表示叢集中同一份資料有多少個副本,就像下圖的樣子:
從圖中你可以看到,在這個三節點的叢集中,DATA-1 有 2 個副本,DATA-2 有 3 個副本,DATA-3 有 1 個副本。也就是說,副本數可以不等於節點數,不同的資料可以有不同的副本數。
在實現 Quorum NWR 的時候,你需要實現自定義副本的功能。也就是說,使用者可以自定義指定資料的副本數,比如,使用者可以指定 DATA-1 具有 2 個副本,DATA-2 具有 3 個副本,就像圖中的樣子。
2.2寫一致性級別
W,又稱寫一致性級別(Write Consistency Level),表示成功完成 W 個副本更新,才完成寫操作:
從圖中你可以看到,DATA-2 的寫副本數為 2,也就說,對 DATA-2 執行寫操作時,完成了 2 個副本的更新(比如節點 A、C),才完成寫操作。
那麼有的人會問了,DATA-2 有 3 個資料副本,完成了 2 副本的更新,就完成了寫操作,那麼如何實現強一致性呢?如果讀到了第三個資料副本(比如節點 B),不就可能無法讀到更新後的值了嗎?先繼續看下面的內容。
3.讀一致性級別
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),也能返回更新後的那份資料,實現強一致性了。
4.NWR組合
除此之外,關於 NWR 需要你注意的是,N、W、R 值的不同組合,會產生不同的一致性效果,具體來說,有這麼兩種效果:
當 W + R > N 的時候,對於客戶端來講,整個系統能保證強一致性,一定能返回更新後的那份資料。
當 W + R < N 的時候,對於客戶端來講,整個系統只能保證最終一致性,可能會返回舊資料。