分散式系統數據一致性的解決方案

来源:http://www.cnblogs.com/wangweitr/archive/2017/09/11/7505712.html
-Advertisement-
Play Games

分散式系統數據一致性的解決方案 隨著互聯網的發展,電腦系統規模變得越來越大,常規的將所有業務單元集中部署在一個或者若幹個大型機上的集中式架構,已經越來越不能滿足當今大型互聯網系統的快速發展。分散式服務架構以及微服務架構已經越來越受到業界的青睞。而在目前的應用系統中,不管是集中式的部署架構還是分散式 ...


分散式系統數據一致性的解決方案

隨著互聯網的發展,電腦系統規模變得越來越大,常規的將所有業務單元集中部署在一個或者若幹個大型機上的集中式架構,已經越來越不能滿足當今大型互聯網系統的快速發展。分散式服務架構以及微服務架構已經越來越受到業界的青睞。而在目前的應用系統中,不管是集中式的部署架構還是分散式的系統架構,數據的一致性是每個應用系統都需要面臨的問題。

在傳統的集中式部署的系統中,應用一般不存在橫跨多資料庫的情況,藉助關係型資料庫自帶的事務管理機制,關係型資料庫具有ACID特性:原子性(Atomicity)、一致性(Consistency)、隔離性(Isolation)、持久性(Durability),保證數據一致性是比較容易的。而在分散式系統中,一個普通的業務功能,內部可能需要調用部署在多個伺服器上的服務,並操作多個資料庫或分片來實現,情況往往會複雜很多。保證數據一致性也變得更加艱難,再通過傳統的關係型資料庫的事務機制等單一的技術手段和解決方案,已經無法應對和滿足這些複雜的場景了。當然這些問題單純依靠特定的開源框架和組件並不能解決,更多的還是需要根據自己的業務場景,選擇合適的解決方案。本文筆者將給大家介紹幾種業界比較常用的解決數據一致性的實現方案,希望可以起到一個拋磚引玉的作用。

 

 

一.CAP理論和BASE理論

 

1、CAP理論

談及分散式系統,就不能不提到CAP理論,CAP理論由Berkeley的電腦教授Eric Brewer在2000年提出,其核心思想是任何基於網路的數據共用系統最多只能滿足數據一致性(Consistency)、可用性(Availability)和網路分區容忍(Partition Tolerance)三個特性中的兩個,三個特性的定義如下:

 

 

 

 

 

 

 

 

 

 

 

  • 一致性(Consistency):一致性,這個和資料庫ACID的一致性類似,但這裡關註的是所有數據節點上的數據一致性和正確性,而資料庫的ACID關註的是在一個事務內,對數據的一些約束。系統在執行過某項操作後仍然處於一致的狀態。在分散式系統中,更新操作執行成功後所有的用戶都應該讀取到最新值。
  • 可用性(Availability):每一個操作總是能夠在一定時間內返回結果。需要註意"一定時間"和"返回結果"。"一定時間"是指,系統結果必須在給定時間內返回。"返回結果"是指系統返回操作成功或失敗的結果。
  • 分區容忍性(Partition Tolerance):是否可以對數據進行分區。這是考慮到性能和可伸縮性。

    在分散式系統中,同時滿足"CAP定律"中的"一致性"、"可用性"和"分區容錯性"三者是不可能的。在互聯網應用的絕大多數的場景,都需要犧牲強一致性來換取系統的高可用性,系統往往只需要保證"最終一致性",只要這個最終時間是在用戶可以接受的範圍內即可。

     

 

2、BASE理論

BASE是Basically Available(基本可用)、Soft state(軟狀態)和Eventually consistent(最終一致性)三個短語的縮寫。BASE理論是對CAP中一致性和可用性權衡的結果, 是基於CAP定理逐步演化而來的。BASE理論的核心思想是:即使無法做到強一致性,但每個應用都可以根據自身業務特點,採用適當的方式來使系統達到最終一致性接下來看一下BASE中的三要素:

  • 基本可用: 基本可用是指分散式系統在出現不可預知故障的時候,允許損失部分可用性。註意,這絕不等價於系統不可用。
  • 軟狀態: 軟狀態是指允許系統存在中間狀態,並且該中間狀態不會影響系統整體可用性。即允許系統在不同節點間副本同步的時候存在延時。
  • 最終一致性:系統中的所有數據副本經過一定時間後,最終能夠達到一致的狀態,不需要實時保證系統數據的強一致性。最終一致性是弱一致性的一種特殊情況。

BASE理論面向的是大型高可用可擴展的分散式系統,和傳統的事物ACID特性是相反的,它完全不同於ACID的強一致性模型,而是通過犧牲強一致性來獲得可用性,並允許數據在一段時間內是不一致的,但最終達到一致狀態但同時,在實際的分散式場景中,不同業務單元和組件對數據一致性的要求是不同的,因此在具體的分散式系統架構設計過程中,ACID特性和BASE理論往往又會結合在一起。

根據CAP理論和BASE理論,在分散式系統中,我們無法找到一種能夠滿足分散式系統所有系統屬性的一致性解決方案,如果不想犧牲一致性,我們只能放棄可用性,這顯然不能接受。因此,為了保證數據的一致性同時又不影響系統運行的性能,許多分散式系統採用弱一致性來提高性能,一些不同的一致性模型也相繼被提出:

  • 強一致性: 當更新操作完成之後,任何多個後續進程或者線程的訪問都會返回最新的更新過的值。這種是對用戶最友好的,就是用戶上一次寫什麼,下一次就保證能讀到什麼。根據 CAP 理論,這種實現需要犧牲可用性。
  • 弱一致性: 系統並不保證跨進程或者線程的訪問都會返回最新的更新過的值。系統在數據寫入成功之後,不承諾立即可以讀到最新寫入的值,也不會具體的承諾多久之後可以讀到。
  • 最終一致性:弱一致性的特定形式。系統保證在沒有後續更新的前提下,系統最終返回上一次更新操作的值。在沒有故障發生的前提下,不一致視窗的時間主要受通信延遲,系統負載和複製副本的個數影響。DNS 是一個典型的最終一致性系統。

 

 

二、數據一致性的幾種解決方案

1、分散式事務

要想理解分散式事務,我們需要先介紹一下兩階段提交協議。

兩階段提交協議(Two-phase Commit,2PC)經常被用來實現分散式事務。一般分為協調器和若幹事務執行者兩種角色。這裡的事務執行者就是具體的資料庫,抽象點可以說是可以控制給資料庫的程式。 協調器可以和事務執行器在一臺機器上。

在分散式系統中,每個節點雖然可以知曉自己的操作的成功或者失敗,卻無法知道其他節點的操作的成功或失敗。當一個事務跨越多個節點時,為了保持事務的ACID特性,需要引入一個作為協調者的組件來統一掌控所有節點(稱作參與者)。

 

兩階段提交協議在主流開發語言平臺,資料庫產品中都有廣泛應用和實現:

1、在Java平臺下,WebLogic、Webshare等主流商用的應用伺服器提供了JTA的實現和支持。

2、在Windows .NET平臺中,則可以藉助ado.net中的TransactionScop API來編程實現,還必須配置和藉助Windows操作系統中的MSDTC服務。

 

總結:這種實現方式實現比較簡單,比較適合傳統的單體應用,在同一個方法中存在跨資料庫操作的情況。但是因為兩階段的提交會創建多次節點的網路通信,通信時間變長後,事務的時間也相對變長,鎖定的資源時間也變長,造成資源等待時間也變長,這會帶來嚴重的性能問題,因此大部分高併發服務往往都避免使用二階段提交協議,所以後來業界又引入了三階段提交協議來解決該類問題。

 

2、非事務型消息隊列+本地消息表

此方案關鍵是要有個本地消息表,基本思路就是:

  1. 消息生產方,需要額外建一個消息表,並記錄消息發送狀態。消息表和業務數據要在一個事務里提交。
  2. 消息消費方:處理消息並完成自己的業務邏輯。此時如果本地事務處理成功,那發送給生產方一個confirm消息,表明已經處理成功了。如果處理失敗,則將消息放回MQ。
  3. 生產方定時掃描本地消息表,把還沒處理完成的消息重新發送一遍,直到本地消息表中記錄的該消息為已成功狀態。

 

 

 

 

 

 

 

 

 

 

 

 

通過上圖可以看出,消費方會面臨一個問題就是,當消費方完成本地事務處理,給生產方發送CONFIRM消息失敗時,生產方由於本地消息表的消息狀態沒有更新,會進行重試,那麼這時候就存在了消息重覆投遞的問題,這時候消費方收到重覆投遞過來的消息後,要保證消費者調用業務的服務介面的冪等性,即:如果重覆消費,也不能因此影響業務結果,同一消息多次被執行會得到相同的結果。

 

總結:這種方式的根本原理就是:將分散式事務轉換為多個本地事務,然後依靠重試等方式達到最終一致性。這種方式比較常見。如果MQ自身和業務都具有高可用性,理論上是可以滿足大部分的業務場景的。但是由於可能存在的長時間處於中間狀態,不建議交易類業務直接使用。

 

3、事務型消息隊列

事務型消息實際上是一個很理想的想法,目前市面上大部分MQ都不支持事務消息,其中包括目前比較火的kafka。阿裡的RocketMQ是可以支持事務型消息的MQ,根據網傳的資料,大概瞭解到RocketMQ的事務消息相當於在普通MQ的基礎上,提供了2PC的提交介面。把非事務型消息隊列中的消息狀態和重發等用中間件形式封裝了。

舉個例子,Bob向Smith轉賬,那我們到底是先發送消息,還是先執行扣款操作?

好像都可能會出問題。如果先發消息,扣款操作失敗,那麼Smith的賬戶裡面會多出一筆錢。反過來,如果先執行扣款操作,後發送消息,那有可能扣款成功了但是消息沒發出去,Smith收不到錢。除了上面介紹的通過異常捕獲和回滾的方式外,還有沒有其他的思路呢?

下麵以阿裡巴巴的RocketMQ中間件為例,分析下其設計和實現思路。

RocketMQ第一階段發送Prepared消息時,會拿到消息的地址,第二階段執行本地事物,第三階段通過第一階段拿到的地址去訪問消息,並修改狀態。細心的讀者可能又發現問題了,如果確認消息發送失敗了怎麼辦?RocketMQ會定期掃描消息集群中的事物消息,這時候發現了Prepared消息,它會向消息發送者確認,Bob的錢到底是減了還是沒減呢?如果減了是回滾還是繼續發送確認消息呢?RocketMQ會根據發送端設置的策略來決定是回滾還是繼續發送確認消息。這樣就保證了消息發送與本地事務同時成功或同時失敗。如下圖:

 

 

 

 

 

 

 

 

 

 

 

總結:目前各大知名的電商平臺和互聯網公司,幾乎都是採用類似的設計思路來實現"最終一致性"的。這種方式適合的業務場景廣泛,而且比較可靠。不過這種方式技術實現的難度比較大。目前主流的開源MQ(ActiveMQ、RabbitMQ、Kafka)均未實現對事務消息的支持,所以需二次開發。

 

後記: 上述所介紹的幾種方案,筆者也只是大致總結了其基本設計思路,這幾種方案只是眾多解決數據一致性的方案中比較經典的幾種。在如今越來越複雜的分散式系統架構下,數據的一致性,並不是說簡單的引入某個中間件能夠解決的,最終一致性並沒有一個放之四海而皆準的成功實踐。更多的還是根據業務場景、業務特性以及業務不同的發展階段,選擇合適的方式來靈活應對。


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

-Advertisement-
Play Games
更多相關文章
  • PHP操作實現一個多功能購物網站 一、需要實現的頁面: Index.aspx:瀏覽商品頁面,顯示商品列表,用戶可以點擊“加入購物車“。 ViewCart.aspx:查看購物車頁面,顯示已購買的商品信息,可以點擊“刪除“和“提交添加訂單購買”商品 ViewAccount.aspx:查看個人賬戶餘額 L ...
  • 回到目錄 下麵將介紹以下幾個原則,都是軟體設計里的大哥大,大姐大級別的人物! DRY DRY是Do Not Repeat Yourself的簡稱,不要寫重覆的代碼,可以使用代碼重構里的提取到方法,提取到類來做這事 KISS KISS 是Keep it short and simple 的簡稱。意思是 ...
  • 一、引言 我們常常在會在字元串中搜索匹配字元或判斷一個字元串是否符合我們要的格式時,使用正則表達式,可解決問題的背後是一種什麼思想呢?即我們今天要學習的內容,解釋器模式 二、解釋器模式 定義:給定一個語言,定義它的文法的一種表示,並定義一個解釋器,這個解釋器使用該表示來解釋語言中的句子 1.文法:即 ...
  • 一個很簡單的淘寶優惠券搜索助手 大家看看有沒有用吧 下載地址:http://pan.baidu.com/s/1skRHTDF ...
  • 返回碼規範: 統一六位 000000 表示成功! 參數相關返回碼預留100000-199999;系統相關返回碼預留200000-299999;數據中心310000-319999後續項目以此類推,後續根據業務擴展情況新增操作碼需要提前備案! module = 系統碼 optCode = 操作碼 opt ...
  • Spring Cloud Netflix多語言/非java語言支持之Spring Cloud Netflix Sidecar Polyglot support with Sidecar 前言 公司有一個調研要做,調研如何將Python語言提供的服務納入到Spring Cloud管理中來,找到了這個S ...
  • 日誌對大型應用系統或者平臺尤其重要,系統日誌採集、分析是系統運維、維護及用戶分析的基礎。 一、系統日誌分類 一般系統日誌可分為三大類: 1、用戶行為日誌:通過採集系統用戶使用系統過程中,一系列的操作日誌。 2、業務變更日誌:特定業務場景需要,採集某用戶在某時使用某功能,對某業務(對象、數據)進行某操 ...
  • 設計模式(Design Patterns) ——可復用面向對象軟體的基礎 設計模式(Design pattern)是一套被反覆使用、多數人知曉的、經過分類編目的、代碼設計經驗的總結。使用設計模式是為了可重用代碼、讓代碼更容易被他人理解、保證代碼可靠性。 毫無疑問,設計模式於己於他人於系統都是多贏的, ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...