客戶端一致性與多Leader機制------《Designing Data-Intensive Applications》讀書筆記7

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

接著上一篇的內容,我們繼續來梳理分散式系統之中的副本機制與副本一致。上文我們聊到了在可用性與一致性之間的一個折中的一致性等級: 最終一致性 。我們順著上篇的內容,由用戶來分析一致性等級。 1. 客戶端的困擾 上篇文章我們提到了數據系統常用的模型,當提交新數據時,必須將它發送給Leader節點,但是當 ...


接著上一篇的內容,我們繼續來梳理分散式系統之中的副本機制與副本一致。上文我們聊到了在可用性與一致性之間的一個折中的一致性等級:最終一致性。我們順著上篇的內容,由用戶來分析一致性等級。

1. 客戶端的困擾

上篇文章我們提到了數據系統常用的模型,當提交新數據時,必須將它發送給Leader節點,但是當用戶查詢數據時,可以從一個Follower節點讀取該數據。
這樣的模型使十分適合Web應用的讀多寫少的特點。

讀寫一致性

但是倘若Leader與Follower之間以非同步的方式複製的話,會存在一些問題。如下圖所示:如果用戶數據剛剛寫入,而新的數據可能尚未達到Follower節點的副本。在用戶的角度,他們提交的數據看起來似乎丟失了。

用戶無法讀取到新寫入的數據

在這種情況下,我們需要讀寫一致性。對於用戶來說,總是能看到它們最新更新的數據。而其他用戶的更新可能需要一定的時間之後才可見。現在新的問題來了,我們如何實現Leader-Follower機制下的讀寫一致性呢?

這裡有一個最簡單粗暴的規則是:用戶可以選擇總是從Leader節點那裡讀取自己寫入的數據,然後選擇自從Follower節點處讀取其他用戶寫入的數據。(註:這裡的技巧十分巧妙,十分適合在多用戶下的隔離,但是僅僅適用於每個用戶都僅僅修改自己數據的場景。)

所以更好的方式是時間戳機制,客戶端可以通過記錄最近一次寫入的時間戳,然後數據系統需要確保為該用戶提供的任何讀取的副本至少在該時間戳之後更新。如果一個副本還沒有達到最新的時間戳,則該讀取需要由另一個副本處理,或者等待可本節點的副本跟進到滿足要求的時間戳。時間戳可以是邏輯時間戳(表示寫入順序的命令,如日誌序列號)或實際系統時鐘(強依賴系統時鐘的話,需要處理時鐘回撥等問題,十分麻煩~~~)。

單調讀一致性

解決了讀寫一致性,我們再來看看下麵的這個場景:
單調讀時在不同副本的幻讀現象

因為用戶可以從多個不同的副本進行多次讀取,則可能發生這種情況。如上圖所示,用戶2345進行了兩次相同的查詢,第一次訪問了Follower1節點,第二次查詢訪問了Follower2節點。第一次查詢返回一個最近由用戶1234添加的註釋,但是第二次查詢並沒有上次查詢的註釋了,因為滯後的Follower還沒有同步到之前的寫入註釋的操作。如果用戶2345第一次看到用戶1234的註釋出現,然後再次查詢它時卻消失了,這對用戶2345來說是非常令人困惑的。

單調讀一致性來是保證這種異常不會發送。當客戶讀到的數據,保證不會看到一個舊的數據。要滿足單調讀一致性。實現單調讀取的一種方法是確保每個用戶總是從同一副本中讀取(不同的用戶可以從不同的副本讀取)。例如,可以根據用戶ID散列選擇副本,而不是隨機選擇。

多數據中心下的交叉設備讀
在多個數據中心的環境下,問題會變的更加複雜。任何需要由Leader節點服務的請求都必須路由轉發到包含Leader的數據中心。當同一用戶從多個設備訪問服務時,另一個複雜的問題出現了,例如桌面Web瀏覽器和移動應用程式。在這種情況下,您可能希望在讀寫一致性的基礎之上提供交叉設備讀:如果用戶輸入某個設備上的一些信息,然後在另一個設備上查看,則應該看到他們剛剛輸入的信息。如果需要提供交叉設備讀,記錄用戶上次更新的時間戳是十分困難的,因為一個設備不知道其他設備上發生了什麼更新。假如你的副本分佈在不同的數據中心,也不能保證不同設備的連接將被路由引導到同一數據中心。

小結:當使用一個最終一致性的數據系統時,如果複製延遲增加到幾分鐘甚至幾小時,就需要考慮應用程式的行為。如果答案是“沒有問題”,那太好了。但如果應用程式對一致性敏感,則應用程式需要提供額外的處理邏輯來處理特殊的場景,如對某些特殊的讀取操作,可以限定只對Leader節點執行某些類型的讀取。但是,在應用程式代碼中處理這些問題會很複雜,很容易出錯。事務確保了許多一致性模型,使應用程式更簡單。然而,在向分散式的環境之中,許多數據系統放棄了對事務的支持,因為事務會大大降低分散式環境之中系統的性能與可用性。所以,最終一致性能夠使用的場景有限,我們還是要按需選擇,避免踩坑。

2. 多Leader機制

在多數據中心的環境下,如果僅僅只有一個Leader,所以每次寫操作都必須訪問同一個數據中心,這將會導致延遲大大提高。所以我們可以考慮多Leader的機制。在多Leader機制可以在每個數據中心中設置一個Leader。下圖展示了多Leader機制的結構:
多Leader機制的結構
在數據中心內部,保持前文提到的Leader-Follower機制。而跨數據中心的Leader之間通過衝突協調進行數據同步。我們來梳理一下多Leader機制的一些特點

  • 性能

在多Leader機制中,每個寫操作可以在本地數據中心進行處理,再非同步複製到其他的數據中心。因此可以大大降低跨數據中心的網路延遲,性能表現顯然會更好。

  • Leader失效

在單Leader的機制里,如果數據中心失效,則故障轉移可以使另一個數據中心中的Follower成為Leader。而多Leader機制,每個數據中心可以獨立於其他數據中心繼續運行。

  • 網路的延遲與故障

數據中心之間的通信通常依托於公共互聯網,它相比數據中心內的本地網路更加不可靠。顯然具有非同步複製特性的多Leader機制可以更好地容忍跨數據中心通信的延遲與故障。

寫衝突

雖然多Leader機制具備了很多優勢,它也有一個大缺點是:相同的數據可以在兩個不同的數據中心,一旦數據同時被修改就必須要有機制來解決寫衝突的問題。如下圖所示,考慮一個同時由兩個用戶編輯的wiki頁面。User1將頁面標題從A改為B,User2同時將標題從A改為C。每個用戶的更改都分別成功提交給了Leader1與Leader2。當進行非同步複製時,系統會檢測到衝突:
同時更新同一條記錄而出現寫衝突

在一個單Leader的數據系統之中,User2要麼阻塞,等待第一次寫入完成,要麼中止第二個寫事務,迫使User2重試寫入。而在多Leader機制之中,兩個寫入操作都是成功的,並且衝突只是在稍後的某個時間點非同步檢測到的。有什麼辦法可以解決這樣的問題呢?

  • 避免衝突
    避免衝突:如果應用程式可以確保某個特定記錄的所有寫入都由同一個Leader處理,那麼衝突就不會發生。由於多Leader機制處理衝突十分複雜,避免衝突是經常推薦的方法。(在用戶可以編輯自己的數據的應用程式中,可以確保特定用戶的請求總是路由到同一個數據中心,並使用該數據中心中的Leader處理讀寫請求。不過這隻是一種鴕鳥策略,用戶地理位置的轉移,或者是路由系統的更新,衝突協調仍然不可避免。

  • 收斂到一致狀態
    在單Leader的機制中:如果對同一個欄位有多個更新,最後一個寫入確定欄位的最終值。。而在多Leader的機制中,沒有定義的寫入順序,因此不清楚最終值應該是什麼。所以數據系統必須以收斂的方式解決衝突,這意味著當所有更改都被覆制時,所有副本必須到達相同的最終值。可以為每個寫操作分配一個唯一的ID(例如,一個時間戳,一個長的隨機數,一個UUID或散列的鍵和值),最高的ID值認為是最終值,這種技術被稱為Last Write Win(LWW)。(強依賴系統時間又會造成很多問題,唉,這真的很煩

  • 自定義衝突消解的邏輯
    最合適的解決衝突的方法可能取決於應用程式,該代碼可以在寫或讀時執行:一旦數據系統檢測到複製更改日誌中的衝突,它就調用衝突處理程式。或是在應用程式讀取的階段檢測到衝突時,會將這些數據的多個版本將返回應用程式。應用程式可以提示用戶或自動解決衝突,並將結果寫入資料庫。(Cassandra與CouchDB就是採取了這種機制

多Leader機制的複製拓撲

兩個Leader進行同步時,拓撲結構十分簡單。但是一旦擴展到4,5個Leader,之後多個Leader之間的同步結構又應該是怎麼樣的呢?(雖然在實踐中,很少採用這樣的架構
多Leader機制的拓撲結構

最一般的拓撲結構是圖(c),其中每個節點都將其寫入傳遞給所有的節點。而(a)或(b)採用了環形或星型的結構來減少網路的流量。在環形和星形拓撲中,在到達所有副本之前,寫入可能需要經過幾個節點。因此,節點需要轉發它們從其他節點接收到的數據更改。為了防止無限複製迴圈,每個節點都被賦予唯一的標識符,並且在複製日誌中,每個寫入都用它經過的所有節點的標識符標記。當一個節點接收一個帶有自己標識符的數據更改時,該數據更改將被忽略,因為節點知道它已經被處理了。

環形和星形結構存在的一個問題是,如果有一個節點失效,會中斷其他節點之間的同步消息流,而因為它不允許消息沿著不同的路徑傳播,造成了單點故障。但是All pass的結構也會帶來一些新的問題,由於網路擁塞的原因,各個節點的信息接收順序不一致,如下圖所示:
寫入操作亂序到達

Client A將行插入到一個Leader 1的表,和Client B在Leader 3之中進行更新。而Leader 2收到了不同順序的寫操作:update操作出現在了insert操作之前。為了正確地排列這些事件,我們可以使用一種稱為多版本向量控制(MVCC)的技術。至於什麼是MVVC,我們下一篇繼續來梳理~~( 不是我故意賣關子啊,只是怕寫的太長你們懶得看~~~


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

-Advertisement-
Play Games
更多相關文章
  • 最近在做的一個後臺管理系統,發現一個bug: 問題描述:如果其他列表項都用類為col-xs-12的div包裹,而引入UEditor的部分不用類為col-xs-12的div包裹,那麼其他列表項將無法顯示,UEditor編輯框也顯示不完全; 解決辦法:將引入UEditor的部分也用類為col-xs-12 ...
  • Vuex 是一個專為 Vue.js 應用程式開發的狀態管理模式。它採用集中式存儲管理應用的所有組件的狀態,並以相應的規則保證狀態以一種可預測的方式發生變化。 在 Vue 之後引入 vuex 會進行自動安裝: 可以通過 https://unpkg.com/[email protected] 這樣的方式指定特定的版本 ...
  • 其實json格式化沒想象中的那麼複雜,難點就是json格式化的工作流程。 正好工作上需要,於是就搞了一套json格式化+json著色的方法,原生的方法,可以直接使用。json數據格式化前後對比圖,如下: 下麵是源碼,可以根據個人需求適當修改: ...
  • 在做後臺管理界面的時候,幾乎少不了的一個結構就是樹形結構,用來做菜單導航; 那麼,最希望的就是樹結構的所有數據都是讀取的資料庫,而不是直接代碼當中寫死,那我們就一步一步來看: 一,建表 欄位通常包括:id,text,url,pid 二,使用nodeJS連接資料庫 三,讀取數據 四,把讀過來的數據轉成 ...
  • HTTP緩存是個大公司面試幾乎必考的問題,寫篇隨筆說一下HTTP緩存。 1. HTTP報文首部中有關緩存的欄位 在HTTP報文中,與緩存相關的信息都存在首部里,簡單說一下首部。 首部 HTTP首部欄位向請求報文和相應報文中添加了一些附加信息。本質上來說,它們只是一些鍵值對的列表。比如,下麵的首部行會 ...
  • 基本使用 html: JavaScript: 通過註入路由,我們可以用 this.$router 來訪問它,就像在任何組件里用 this.$router 訪問當前路有一樣。 路由的命名 要鏈接到一個命名路由,可以給 router-link 的 to 屬性傳一個對象: 這跟代碼調用 router.pu ...
  • 對於前端分頁,不懂的人也許會覺得是個笑話,分頁不都是後端的事情嗎?的確不得不承認,處理邏輯性的話,還是後端更加友好,但前端分頁,也有他友好的一面,舉個慄子:伺服器壓力請求減少,換頁時用戶體驗好。直戳主題——前端實現分頁的原理及其步驟 ...
  • 虛擬化和容器化是項目雲化不可避免的兩個問題。虛擬化由於是純平臺操作,一個運行於linux操作系統的項目幾乎不需要做任何改造就可以支持虛擬化。而項目如果要支持容器化則需要做許多細緻的改造工作。容器化相對於虛擬化的優勢也相當明顯,運行於裸機性能高,秒級啟停容器,更不用說開發、測試、佈署一致的環境(Dev... ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...