P2P結構與Quorum機制------《Designing Data-Intensive Applications》讀書筆記8

来源:https://www.cnblogs.com/happenlee/archive/2018/01/28/8370764.html
-Advertisement-
Play Games

前文涉及到了很多與Leader相關的演算法,大家有木有想過,王侯將相,寧有種乎,既然Leader這麼麻煩,乾脆還是採用P2P模型吧,來個大家平等的架構。本篇需要和大家探討的就是多副本下實現民主政治的 Quorum機制 。至於它是怎麼樣解決我們在前文提及的各種問題的,接著這篇文章我們繼續聊聊~~ 1. ...


前文涉及到了很多與Leader相關的演算法,大家有木有想過,王侯將相,寧有種乎,既然Leader這麼麻煩,乾脆還是採用P2P模型吧,來個大家平等的架構。本篇需要和大家探討的就是多副本下實現民主政治的Quorum機制。至於它是怎麼樣解決我們在前文提及的各種問題的,接著這篇文章我們繼續聊聊~~

1. No-Leader機制

有些數據存儲系統放棄了Leader的機制,允許任何副本直接接受用戶的寫操作。(如Amazon的Dynamo,FaceBook的Cassandra,雖然最終FaceBook放棄了Cassandra轉而支持Hbase,但是Uber的強勢介入讓Cassandra後來在開源社區大放異彩。) 每個接受到客戶端寫請求的節點會轉換為一個協調器節點,而協調器節點不強制執行特定的寫入順序。正是這種設計上的差異對資料庫的使用方式與數據模型產生了深遠的影響。

多副本的讀寫

No-Leader機制是怎麼樣消除Leader這個角色的存在的呢?答案也很簡單:多副本讀寫。接下來我們來看一個慄子:

假設我們在數據系統之中採用了三副本的結構,如下圖所示:User 1234 並行地將所有的副本發送給三個存儲節點,並且兩個節點可以接受副本的寫入,但是其中一個節點不線上,所以副本寫入失敗。所以在三個副本中有兩個副本確認寫入成功了:在User 1234收到兩個OK響應之後,User就認為寫入操作是成功的,忽略了一個副本寫入失敗。(當然,不是簡單的就不管這個寫入失敗了,後續會有修複機制來補齊這個副本的數據

image.png

現在假設User 2345開始讀取新寫入的數據。由於一個節點寫入失敗了,所以User 234 可能會得到過期的值作為響應。為瞭解決這個問題,當User 從數據系統之中讀取數據時,它不只是將請求發送到一個副本,而是將讀取請求並行地發送到多個副本節點。User可以從不同節點獲得不同的響應,即來自其他節點的最新值和另一個節點的過期值。這裡通過了版本號用於確定哪個值是更新的值。

副本修複

No-Leader機制導致了數據系統之中可能存在大量過期的值,所以一個節點怎麼來修複自身的副本來獲取最新值的過程我們就稱之為副本修複,No-Leader機制也是通過這樣的方式來達到最終一致性的。通常會有這樣幾種方式:

  • 讀修複
    當用戶並行讀取多個節點時,它可以獲取到其他過期的值的響應。所以用戶會發現其中有些節點擁有過期的值,這時用戶可以主動將新值寫入該節點。這種方法稱之為讀修複

  • 反熵過程(其實是一個物理學概念)
    每個數據存儲節點都會有一個後臺進程,不斷的比對自己的副本與其他節點副本的差異,發現自己擁有過期的值之後,會主動修複自己過期的副本。與基於寫入順序日誌不同,這種反熵過程不以任何特定的順序複製寫操作,並且在複製數據之前可能會有顯著的延遲。

2. Quorum機制

上文之中提及的例子在三個副本中的兩個之上寫入成功,我們認為寫操作成功了。但是如果三個副本只有的一個副本寫入成功了?這時的寫操作是否是成功的呢?

答案是否定的?這裡其實就是簡單的鴿巢原理,這裡我不做數學證明瞭,大家有興趣的可以自行證明一下。
假設有n個副本,每次寫操作必須由w個節點確認為成功,每個讀操作讀取r個節點。(在上文的例子中,n=3,w=2,r=2)。只要w + r > n,如果讀和寫操作的總次數大於n,那麼讀和寫操作必然至少有一個副本是相同的,也就是讀操作必然可以讀到最新寫操作的數據。這被我們稱之為:Quorum機制,每次讀寫都需要達到法定人數。

通常 n、w和r通常是可配置的,根據您的需要來修改這些數字。一個常見的選擇是使n為奇數(通常為3或5),並設置w=r=(n + 1)/ 2 。如下圖所示,如果w < n,如果有n - w個節點不可用,我們仍然可以處理寫操作。同樣的如果r<n,如果有n - r個節點不可用,我們仍然可以處理讀操作。而如果小於所需的w或r節點可用,則寫或讀操作就會返回錯誤。

  • n=3,w=2,r=2,我們可以容忍一個不可用的節點。
  • n=5,w=3,r=3,我們可以容忍兩個不可用的節點。

Quorum機制保證了一定能讀到最新的副本

高可用與Hinted handoff

Quorum機制實現了最終一致性的模型,但是在可用性上還是有一些極端情況,沒法很好處理。如:出現網路抖動時,但是可能系統仍然有許多正常工作的節點。但是副本應該被寫入的n個節點發生網路問題,導致了會少於w或r個成功的讀寫操作,由於不能達到法定的人數,讀寫操作都會失敗。所以這時候資料庫系統的設計者面臨權衡取捨,能不能通過一些機制,實現更好的可用性呢?

所以這種情況下,我們就可以利用Hinted handoff了(原諒我翻譯不好)。這種方式是怎麼樣實現的呢?寫和讀操作仍然需要w和r成功的響應,但是可以不強制一定要寫如指定的n個節點 (這個涉及到一致性哈希,數據分佈的知識,暫時要是理解不了,我後續會有專門的專題來寫這個內容,可以先放一放。) 打個比方說,如果你把自己鎖在門外,你可能會敲鄰居的門,問你是否可以暫時呆在他們的沙發上,一旦你找到鑰匙了,你就自己回家了。所以其他節點可以暫存本應該放在另一個節點上的副本,一旦網路中斷被修複,其他節點就會把副本轉交給主人節點。

所以這種模式既保證了不違反Quorum機制,也大大提高了系統的可用性,被No-leader數據系統廣泛採用。

3 寫入衝突與Quorum機制

同樣的Quorum機制的設計本身就可以允許併發讀寫操作,並容忍網路中斷與高峰延遲。但是這也必然會帶來一致性問題,我們來看下麵這個例子:

如圖所示,有兩個Client A與B,同時寫入關鍵字X在一個三副本的數據存儲系統之中。Node 1接收來自A的寫入,但由於網路中斷而從未接收來自B的寫入。Node 2首先接收來自A的寫入,然後接收B寫入。而Node 3則是首先接收來自B的寫入,然後接收A的寫入。Node 2認為X的最終值是B,而其他Node認為最終值是A.
併發寫導致副本衝突

在這樣的場景下如何仲裁寫入結果成為了一個大問題,思路和我們之前提到的類型:

  • Last Write Win
    我們可以為每個寫操作附加一個時間戳,選擇最大的時間戳作為最新的值,並丟棄任何具有早期時間戳的寫操作的值。這種衝突解決演算法,稱為Last Write Win。這種情況要求每個寫操作具有冪等性,否則會出現寫丟失的情況,如何能保證不出現依賴的寫丟失呢?

  • 合併“happens-before”關係
    每當有兩個操作A和B時,有三種可能:A發生在B之前,B發生在A之前,A或B是併發的。我們需要的是一個演算法,告訴我們兩個操作是否併發。如果一個操作在另一個操作之前發生,那麼後面的操作應該覆蓋前面的操作,但是如果操作是並行的,那麼我們需要解決一個衝突。怎麼樣去捕獲併合並“happen-before”的關係呢?可以在伺服器節點維護一個版本號,每次寫操作時遞增版本號,並將新版本號存儲在寫入的值中。
    • 客戶端
      當客戶端讀取一個鍵時,服務節點會返回所有未被覆蓋的值,以及最新版本號。當客戶端需要寫一個鍵時,它必須包含從先前讀取中的版本號,並且它必須合併它在前面讀取中接收到的所有值。
    • 伺服器
      當伺服器接收到具有特定版本號的寫入時,它可以覆蓋該版本號或以下的所有值,因為它知道已經合併到新值,但必須保留所有值具有更高版本號。
  • 版本向量

合併“happen-before"使用一個單一的版本號來捕捉操作之間的依賴關係,但這不足以解決當有多個副本並行寫入的情況。相反,我們需要使用每個副本的版本號以及每個鍵。每個副本在處理寫時遞增自己的版本號,並跟蹤從其他副本中看到的版本號。此信息指示要覆蓋哪些值以及作為兄弟版本保存著哪些值。而所有副本的版本號的集合稱為版本向量。版本向量從數據節點發送給客戶端,所以版本向量讓我們可以區分覆蓋寫與發並行寫操作。

4. 小結

好了,到此為止我們終於總結完整了分散式系統之中的副本機制。從Leader-Follower 機制到多Leader機制,最後到No-Leader的機制,並且詳細總結了各個機制的實現細節與優缺點,希望大家閱讀完之後也能有所收穫。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • angularJS使用的MVC為何不屬於二十三種設計模式之一? MVC被GoF (Gang of Four,四人組, 《Design Patterns: Elements of Reusable Object-Oriented Software》/《設計模式》一書的作者:Erich Gamma、Ri ...
  • 本文最初發表於 "博客園" ,併在 "GitHub" 上持續更新 前端的系列文章 。歡迎在GitHub上關註我,一起入門和進階前端。 以下是正文。 京東網頁上,可以看到下麵這種tab欄的切換: 我們把模型抽象出來,實現一下。 舉例引入:滑鼠懸停時,current元素的背景變色 本段我們先舉一個例子, ...
  • 前端路由的兩種實現方式: 1. location.hash + hashchange 2. history API pushState(state, title, url)添加記錄,replaceState修改記錄,popState(只有在前進後退時觸發) ...
  • vue.js 變化 從 github 的發佈記錄我們可以看到2017年 vue.js 的第一個發佈為 v2.1.9,最後一個為 v2.5.13,主要發佈小版本 2.2~2.5。這些發佈提升了vue 與 TypeScript 的結合、改進了對服務端渲染(SSR)和 native 渲染的支持、提供了更好 ...
  • 今年的雪特別美,長沙自從08年後的最大的一場學了,今天小編給大家製作一個表白特效,希望大家喜歡,如果你是程式員希望對你有幫助,追到你喜歡的女孩,哈哈~追不到對象,小編現場吃學給你大家看 今年的雪特別美,長沙自從08年後的最大的一場學了,今天小編給大家製作一個表白特效,希望大家喜歡,如果你是程式員希望 ...
  • 這幾天使用H5開發了一個仿微信聊天前端界面,尤其微信底部編輯器那塊處理的很好,使用HTML5來開發,雖說功能效果並沒有微信那麼全,但是也相當不錯了,可以發送消息、表情,發送的消息自動回滾定位到底部,另外可以對消息、圖片、視頻有不同的右鍵處理提示,還有打賞、占屏等操作。 html代碼片段: Javas ...
  • 最近想找換一份工作,於是去面試了一家比較大的公司,以下是面試官問的幾個關於技術的面試題。 一.css裡面有個position,你知道它都有那幾個值嗎,以及它們的作用是什麼? 這個我回答的是: position一共有absolute,fixed,relative,static,inherit這幾個值, ...
  • A代碼編輯器,線上模版編輯,仿開發工具編輯器,pdf線上預覽,文件轉換編碼 B 集成代碼生成器 [正反雙向](單表、主表、明細表、樹形表,快速開發利器)+快速表單構建器 freemaker模版技術 ,0個代碼不用寫,生成完整的一個模塊,帶頁面、建表sql腳本,處理類,service等完整模塊 C 集 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...