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

来源: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
  • 前言 本文介紹一款使用 C# 與 WPF 開發的音頻播放器,其界面簡潔大方,操作體驗流暢。該播放器支持多種音頻格式(如 MP4、WMA、OGG、FLAC 等),並具備標記、實時歌詞顯示等功能。 另外,還支持換膚及多語言(中英文)切換。核心音頻處理採用 FFmpeg 組件,獲得了廣泛認可,目前 Git ...
  • OAuth2.0授權驗證-gitee授權碼模式 本文主要介紹如何筆者自己是如何使用gitee提供的OAuth2.0協議完成授權驗證並登錄到自己的系統,完整模式如圖 1、創建應用 打開gitee個人中心->第三方應用->創建應用 創建應用後在我的應用界面,查看已創建應用的Client ID和Clien ...
  • 解決了這個問題:《winForm下,fastReport.net 從.net framework 升級到.net5遇到的錯誤“Operation is not supported on this platform.”》 本文內容轉載自:https://www.fcnsoft.com/Home/Sho ...
  • 國內文章 WPF 從裸 Win 32 的 WM_Pointer 消息獲取觸摸點繪製筆跡 https://www.cnblogs.com/lindexi/p/18390983 本文將告訴大家如何在 WPF 裡面,接收裸 Win 32 的 WM_Pointer 消息,從消息裡面獲取觸摸點信息,使用觸摸點 ...
  • 前言 給大家推薦一個專為新零售快消行業打造了一套高效的進銷存管理系統。 系統不僅具備強大的庫存管理功能,還集成了高性能的輕量級 POS 解決方案,確保頁面載入速度極快,提供良好的用戶體驗。 項目介紹 Dorisoy.POS 是一款基於 .NET 7 和 Angular 4 開發的新零售快消進銷存管理 ...
  • ABP CLI常用的代碼分享 一、確保環境配置正確 安裝.NET CLI: ABP CLI是基於.NET Core或.NET 5/6/7等更高版本構建的,因此首先需要在你的開發環境中安裝.NET CLI。這可以通過訪問Microsoft官網下載並安裝相應版本的.NET SDK來實現。 安裝ABP ...
  • 問題 問題是這樣的:第三方的webapi,需要先調用登陸介面獲取Cookie,訪問其它介面時攜帶Cookie信息。 但使用HttpClient類調用登陸介面,返回的Headers中沒有找到Cookie信息。 分析 首先,使用Postman測試該登陸介面,正常返回Cookie信息,說明是HttpCli ...
  • 國內文章 關於.NET在中國為什麼工資低的分析 https://www.cnblogs.com/thinkingmore/p/18406244 .NET在中國開發者的薪資偏低,主要因市場需求、技術棧選擇和企業文化等因素所致。歷史上,.NET曾因微軟的閉源策略發展受限,儘管後來推出了跨平臺的.NET ...
  • 在WPF開發應用中,動畫不僅可以引起用戶的註意與興趣,而且還使軟體更加便於使用。前面幾篇文章講解了畫筆(Brush),形狀(Shape),幾何圖形(Geometry),變換(Transform)等相關內容,今天繼續講解動畫相關內容和知識點,僅供學習分享使用,如有不足之處,還請指正。 ...
  • 什麼是委托? 委托可以說是把一個方法代入另一個方法執行,相當於指向函數的指針;事件就相當於保存委托的數組; 1.實例化委托的方式: 方式1:通過new創建實例: public delegate void ShowDelegate(); 或者 public delegate string ShowDe ...