分散式一致性

語言: CN / TW / HK

政採雲技術團隊.png

卡西.png

分散式事務一致性方案

1、什麼是分散式事務

1.1 事務

資料庫事務(簡稱:事務,Transaction)是指資料庫執行過程中的一個邏輯單位,由一個有限的資料庫操作序列構成。眾所周知,事務擁有 ACID 四個特性,即:原子性( Atomicity ),一致性( Consistency ),隔離性( Isolation ),永續性(Durability)。

1.2 分散式事務

區別於基於單個服務單一資料庫資源訪問的本地事務(Local Transaction),分散式事務指事務的參與者、支援事務的伺服器、資源伺服器以及事務管理器分別位於不同的分散式系統的不同節點之上,且屬於不同的應用,分散式事務需要保證這些操作要麼全部成功,要麼全部失敗。本質上來說,分散式事務就是為了保證不同資料庫的資料一致性

1.3 分散式事務應用架構

本地事務主要限制在單個會話內,不涉及多個數據庫資源。但是在基於 SOA(Service-Oriented Architecture,面向服務架構) 的分散式應用環境下,越來越多的應用要求對多個數據庫資源、多個服務以及多個服務對應的資料庫資源的訪問都能納入到同一個事務當中,分散式事務應運而生。

1.4 資料一致性的基礎理論

  • 弱一致性 Weak:系統並不保證續程序或者執行緒的訪問都會返回最新的更新過的值。系統在資料寫入成功之後,不承諾立即可以讀到最新寫入的值,也不會具體的承諾多久之後可以讀到。比如:某些 cache 系統,百度搜索引擎。
  • 最終一致性 Eventually:弱一致性的特定形式。系統保證在沒有後續更新的前提下,系統最終返回上一次更新操作的值。在沒有故障發生的前提下,不一致視窗的時間主要受通訊延遲,系統負載和複製副本的個數影響。比如:DNS,電子郵件、Amazon S3,Google 搜尋引擎這樣的系統。

  • 強一致性 Strong:新的資料一旦寫入,任何多個後續程序或者執行緒的訪問都會返回最新的更新過的值。比如:檔案系統,RDBMS,Azure Table 都是強一致性的。

1.5 CAP 定理

CAP 理論由加州大學伯克利分校的計算機教授 Eric Brewer 在 2000 年提出,其核心思想是任何基於網路的資料共享系統最多隻能滿足資料一致性(Consistency)、可用性 (Availability)和網路分割槽容忍(Partition Tolerance)三個特性中的兩個。

  • C (一致性):對某個指定的客戶端來說,讀操作能返回最新的寫操作。

對於資料分佈在不同節點上的資料來說,如果在某個節點更新了資料,那麼在其他節點如果都能讀取到這個最新的資料,那麼就稱為強一致,如果有某個節點沒有讀取到,那就是分散式不一致。

  • A (可用性):非故障的節點在合理的時間內返回合理的響應(不是錯誤和超時的響應)。可用性的兩個關鍵一個是合理的時間,一個是合理的響應。

合理的時間指的是請求不能無限被阻塞,應該在合理的時間給出返回。合理的響應指的是系統應該明確返回結果並且結果是正確的,這裡的正確指的是比如應該返回 50,而不是返回 40。

  • P (分割槽容錯性):當出現網路分割槽後,系統能夠繼續工作。打個比方,這裡叢集有多臺機器,有臺機器網路出現了問題,但是這個叢集仍然可以正常工作。

對於 CA 來說,放棄了 P,那麼當發生分割槽現象時,為了保證一致性,這個時候必須拒絕請求,但是 A 又不允許,在分散式系統中,網路無法 100% 可靠,分割槽其實是一個必然現象,所以分散式系統理論上不可能選擇 CA 架構,只能選擇 CP 或者 AP 架構。

對於 CP 來說,放棄可用性,追求一致性和分割槽容錯性,我們的 ZooKeeper 其實就是追求的強一致。

對於 AP 來說,放棄一致性(這裡說的一致性是強一致性),追求分割槽容錯性和可用性,這是很多分散式系統設計時的選擇,後面的 BASE 也是根據 AP 來擴充套件。

因此大家按照 CAP 理論在對熱門的分散式系統進行判定,譬如認為 HBase、MongoDB 等是一個 CP 系統,Cassandra、Dynamo 等是 AP 系統,其實並不嚴謹,理由是 CAP 理論是對分散式系統中一個數據無法同時達到可用性和一致性的斷言,而一個系統中往往存在很多型別的資料,部分資料(比如金額類)是需要強 一致性的,而另外一部分資料(比如訪問量等)並不要求強一致性,所以拿 CAP 並不是來劃分系統的, 而是指引設計者在設計分散式系統時需要區分各種資料的特點,並仔細考慮在小概率的網路分割槽發生時究竟為該資料選擇可用性還是一致性。

1.6 BASE 理論

核心思想:

  • 基本可用(Basically Available):指分散式系統在出現故障時,允許損失部分的可用性來保證核心功能可用。
  • 軟狀態(Soft State):指允許分散式系統存在中間狀態(也叫軟狀態),該中間狀態不會影響到系統的整體可用性。
  • 最終一致性(Eventual Consistency):經過一段時間後,所有的分散式節點資料達到一致狀態。

BASE 理論通過犧牲強一致性來獲取最終一致性,當出現故障時允許部分不可用但要保證核心功能可用,允許資料在一段時間內不一致,但最終達到一致狀態,滿足 BASE 理論的事物,稱之為柔性事務。

二、分散式事務一致性解決方案

2.1 兩階段提交(2PC)

2PC(Two Phase Commitment Protocol)是分散式事務中最經典的事務型別之一

兩個角色

一個事務協調者(coordinator):負責協調多個參與者進行事務投票及提交或回滾 ​ 多個事務參與者(participants):即本地事務執行者

兩個階段步驟

階段一:提交事務請求(投票階段)  

​ 1 事務詢問:協調者向所有的參與者傳送事務內容,詢問是否可以執行事務提交,等待迴應。 

2 執行事務:各節點參與者執行本地事務,並記錄 Undo 和 Redo 日誌  

​ 3 參與者反饋事務:如果成功執行事務,向協調者反饋 Yes,否則 No

階段二:執行事務提交  

  • 如果階段一反饋都是 Yes,則:    

    1 協調者發起事務提交請求

    2 參與者提交事務(commit)   

    3 反饋事務提交結果   

    4 完成事務 

  • 如果階段一有反饋 No,則:

    1 協調者傳送回滾請求

    2 參與者事務回滾(rollback)   

    3 返回回滾事務結果  

    4 中斷事務   

如果任一資源管理器在第一階段返回準備失敗,那麼事務管理器會要求所有資源管理器在第二階段執行回滾操作。通過事務管理器的兩階段協調,最終所有資源管理器要麼全部提交,要麼全部回滾,最終狀態都是一致的。

3PC

兩段提交最大的問題就是:第二階段時,參與者沒有收到協調者的 commit/rollback 的指令,參與者就會一直處於等待指令狀態,整個事務 block 住。即:協調者的可用性是個關鍵。

因些引出了升級版的三段提交 3PC,3PC 把 2PC 的第一個階段變成了兩段,其核心理念是:在詢問的時候並不鎖定資源,除非所有人都同意了,才開始鎖資源。但三階段提交也存在一些缺陷,即:如果參與者收到了 preCommit 訊息後,出現了網路分割槽,那麼參與者等待超時後,都會進行事務的提交,必然會出現事務不一致的問題。

優缺點

優點: 儘量保證了資料的強一致,適合對資料強一致要求很高的關鍵領域。

缺點: 由於是強一致性,資源需要在事務內部等待,效能影響較大,吞吐率不高,不適合高併發與高效能的業務場景;因此並不適合在微服務架構體系下使用

2.2 補償事務 TCC(Try-Confirm-Cancel

TCC 將事務提交分為 Try - Confirm - Cancel 三個操作。是改進版的二階段提交,Try 為第一階段,Confirm - Cancel 為第二階段。

  1. Try:業務校驗,預留必須業務資源。
  2. Confirm:真正執行業務,不再做業務校驗;使用 Try 階段預留的業務資源;try 成功,confirm 必定成功,需滿足冪等性。
  3. Cancel:釋放 Try 階段預留的業務資源;需滿足冪等性。

其核心在於將業務分為兩個操作步驟完成。不依賴 RM 對分散式事務的支援,而是通過對業務邏輯的分解來實現分散式事務。

  • 當所有 try 方法均執行成功時,對全域性事物進行提交,即由事物管理器呼叫每個微服務的 confirm 方法;
  • 當任意一個方法 try 失敗(資源不足、網路異常、程式碼異常等等),由事物管理器呼叫每個微服務的 cancle 方法對全域性事務進行回滾;
  • 按照 TCC 的協議,Confirm 和 Cancel 是隻返回成功,不會返回失敗。如果由於網路問題,或者伺服器臨時故障,那麼事務管理器會進行重試,最終成功。

優缺點

​ 優點: 相對於 2PC 較為簡單,Try 操作可以靈活選擇業務資源的鎖定粒度

​ 缺點:Canfirm 和 Cancel 的冪等性很難保證;

​ TCC 屬於應用層的一種補償方式,對業務侵入性比較大,耦合性高;

​ 開發成本很高,適用場景十分有限。

2.3 本地訊息表

本地訊息表的核心思想是將分散式事務拆分成本地事務進行處理,是 eBay 架構師 Dan Pritchett 提出的分散式系統一致性問題的解決方案,也是業界使用最多的。

其流程圖如下:

基本思路就是:

訊息生產方,需要在業務資料庫中額外建立一個訊息表,並記錄訊息傳送狀態,業務資料與訊息在同一事務中提交。事務提交後,訊息會經過 MQ 傳送給消費方,如果訊息傳送失敗,會進行重試傳送。

訊息消費方處理 MQ 發來的訊息,如果本地事務處理成功,表明已經處理成功了,如果處理失敗,那麼就會重試執行。如果是業務上面的失敗,可以給生產方傳送一個業務補償訊息,通知生產方進行回滾等操作。

生產方和消費方定時掃描本地訊息表,把還沒處理完成的訊息或者失敗的訊息再發送一遍。如果有靠譜的自動對賬補賬邏輯,這種方案還是非常實用的。

優缺點

​ 優點: 一種非常經典最終一致性實現方案。實現邏輯簡單,開發成本⽐較低

​ 缺點:與業務場景繫結,⾼耦合,不可公⽤;本地訊息表與業務資料表在同⼀個庫,佔⽤業務系統資源,量⼤可能會影響

2.4 MQ(非事務訊息)

通常使用非事務訊息支援的 MQ 產品,我們很難將業務操作與對 MQ 的操作放在一個本地事務域中管理。以“轉賬”為例,始終沒有辦法保證在扣款完成後,對方賬戶增加的 MQ 訊息投遞一定能成功。

我們來分析下可能的情況:

  • 正常的流程:本地操作成功,MQ 投遞訊息也成功 ;

  • 異常流程: 本地操作失敗,不會向 MQ 中投遞訊息了;

​ 本地操作成功,MQ 訊息投遞時失敗,丟擲了異常,本地操作回滾;

目前來看,這些情況都沒有一致性問題。

那麼:若本地操作成功,MQ 投遞訊息也成功,但 MQ 消費方消費失敗的情況該如何處理?

  • 訊息不能失效或者丟失,需要保證訊息與業務操作一致,

主流的 MQ 產品都具有持久化訊息的功能。如果消費者宕機或者消費失敗,都可以執行重試機制的。

  • 避免訊息重複消費,即使重複消費也不能因此影響業務結果。

​ 保證消費者介面冪等性;儲存消費日誌或消費狀態表,便於判斷;

但有一種場景,消費方程式異常或因異常資料引起的程式異常,即使重試多次仍會失敗的場景,仍無法保證系統間的一致性,這種情況只能通過設定預警人工訂正等其他補償方式來解決。

優缺點

優點: 效能和吞吐量是優於使用關係型資料庫訊息表的方案

​ 如果 MQ 自身和業務都具有高可用性,理論上是可以滿足大部分的業務場景的

缺點:無法完全保證系統間的一致性

2.5 MQ 事務訊息

目前一些主流的 MQ 比如 RabbitMQ 和 Kafka 都不支援事務訊息,Apache RocketMQ 在 4.3.0 版中已經支援分散式事務訊息,採用了 2PC(兩階段提交)+ 補償機制(事務狀態回查)的思想來實現了提交事務訊息,同時增加一個補償邏輯來處理二階段超時或者失敗的訊息,如下圖所示。

2.5.1 事務訊息流程

(1) 正常事務訊息的傳送及提交

  1. 生產者傳送 half 訊息(半訊息 )到服務端;
  2. 服務端將訊息持久化之後,給生產者響應訊息寫入結果(ACK 響應);

  3. 生產者根據傳送結果執行本地事務邏輯(如果寫入失敗,此時 half 訊息對業務不可見,本地邏輯不執行);

  4. 生產者根據本地事務執行結果向 Broker 服務端提交二次確認(Commit 或是 Rollback),Broker 服務端收到 Commit 狀態則將半事務訊息標記為可投遞,訂閱方最終將收到該訊息;Broker 服務端收到 Rollback 狀態則刪除半事務訊息,訂閱方將不會接收該訊息;

(2) 事務訊息的補償流程

  1. 在網路閃斷或者是應用重啟的情況下,可能導致生產者傳送的二次確認訊息未能到達服務端,經過固定時間後,服務端將會對沒有 Commit/Rollback 的事務訊息(pending 狀態的訊息)進行“回查”;
  2. 生產者收到回查訊息後,檢查回查訊息對應的本地事務執行的最終結果;

  3. 生產者根據本地事務狀態,再次提交二次確認給服務端,然後服務端重新對半事務訊息 Commit 或者 Rollback;

2.5.2 事務訊息原理

設計思想:RocketMQ 事務訊息最主要的特點是:

  • 一階段傳送的 Half 訊息對使用者是不可見的;
  • 事務回查機制

那麼如何做到寫入訊息但是對使用者不可見呢?

RocketMQ 事務訊息的做法是:如果訊息是 half 訊息,將備份原訊息的主題與訊息消費佇列,然後改變主題為 RMQ_SYS_TRANS_HALF_TOPIC。由於消費組未訂閱該主題,故消費端無法消費 half 型別的訊息。

如何實現事務回查? Broker 會啟動一個訊息回查的定時任務,定時從事務訊息 queue 中讀取所有待反查的訊息。針對每個需要反查的半訊息,Broker 會給對應的 Producer 發一個要求執行事務狀態反查的 RPC 請求。然後根據 RPC 返回響應中的反查結果,來決定這個半訊息是需要提交還是回滾,或者後續繼續來反查。最後,提交或者回滾事務,將半訊息標記為已處理狀態。

優缺點

優點:

  • 系統解耦:訊息之間獨立儲存,系統之間訊息完成事務
  • 複雜度低,實現較為簡單

缺點:

  • 一次訊息需要傳送兩次請求(half 訊息+commit or rollback)
  • 業務中需要實現訊息狀態回查介面
  • 目前主流 MQ 中只有 RocketMQ 支援事務訊息

2.6 Seata

Seata 是一款開源的分散式事務解決方案,致力於提供高效能和簡單易用的分散式事務服務。Seata 將為使用者提供了 AT、TCC、SAGA 和 XA 事務模式,為使用者打造一站式的分散式解決方案。

  • AT 模式是無侵入的分散式事務解決方案,使用者只需關注自己的“業務 SQL”,使用者的 “業務 SQL” 作為一階段,Seata 框架會自動生成事務的二階段提交和回滾操作,適用於不希望對業務進行改造的場景,幾乎 0 學習成本。
  • TCC 模式需要使用者根據自己的業務場景實現 Try、Confirm 和 Cancel 三個操作。事務發起方在一階段執行 Try 方法,在二階段提交執行 Confirm 方法,二階段回滾執行 Cancel 方法。TCC 模式是高效能分散式事務解決方案,適用於核心系統等對效能有很高要求的場景。
  • Saga 模式是長事務解決方案,適用於業務流程長且需要保證事務最終一致性的業務系統,Saga 模式一階段就會提交本地事務,無鎖,長流程情況下可以保證效能,多用於渠道層、整合層業務系統。事務參與者可能是其它公司的服務或者是遺留系統的服務,無法進行改造和提供 TCC 要求的介面,也可以使用 Saga 模式。
  • XA 模式是分散式強一致性的解決方案,但效能低而使用較少。

在我們之前的文章中已詳細講過 Seata 相關內容,感興趣的朋友可以點選檢視:https://mp.weixin.qq.com/s/3dNSF1MErKKkamYEYJhylQ

小結

綜上所述,分散式系統的事務一致性本身就是一個技術難題,其主要難點在於“網路通訊的不可靠”。以上介紹的所有方案均有其優缺點和各自適用的場景,目前也沒有一種很簡單很完美的方案能夠應對所有場景。只能通過“確認機制”、“重試機制”、“補償機制”等各方面來解決一些問題。在綜合考慮可用性、效能、實現複雜度等各方面的情況上,比較好的選擇是“非同步確保最終一致性”,只是具體實現方式上有一些差異。

參考:

分散式系統的事務處理

分散式系統事務一致性解決方案

常用的分散式事務解決方案介紹有多少種?

https://blog.csdn.net/weixin_48563689/article/details/109136478

https://www.cnblogs.com/peteremperor/p/13551408.html

推薦閱讀

Lucene 查詢原理解析

Unsafe 魔法類應用體現 (LockSupport)

資料中臺建設實踐(二)- 資料治理之資料質量

政採雲Flutter低成本螢幕適配方案探索

招賢納士

政採雲技術團隊(Zero),一個富有激情、創造力和執行力的團隊,Base 在風景如畫的杭州。團隊現有300多名研發小夥伴,既有來自阿里、華為、網易的“老”兵,也有來自浙大、中科大、杭電等校的新人。團隊在日常業務開發之外,還分別在雲原生、區塊鏈、人工智慧、低程式碼平臺、中介軟體、大資料、物料體系、工程平臺、效能體驗、視覺化等領域進行技術探索和實踐,推動並落地了一系列的內部技術產品,持續探索技術的新邊界。此外,團隊還紛紛投身社群建設,目前已經是 google flutter、scikit-learn、Apache Dubbo、Apache Rocketmq、Apache Pulsar、CNCF Dapr、Apache DolphinScheduler、alibaba Seata 等眾多優秀開源社群的貢獻者。如果你想改變一直被事折騰,希望開始折騰事;如果你想改變一直被告誡需要多些想法,卻無從破局;如果你想改變你有能力去做成那個結果,卻不需要你;如果你想改變你想做成的事需要一個團隊去支撐,但沒你帶人的位置;如果你想改變本來悟性不錯,但總是有那一層窗戶紙的模糊……如果你相信相信的力量,相信平凡人能成就非凡事,相信能遇到更好的自己。如果你希望參與到隨著業務騰飛的過程,親手推動一個有著深入的業務理解、完善的技術體系、技術創造價值、影響力外溢的技術團隊的成長過程,我覺得我們該聊聊。任何時間,等著你寫點什麼,發給 [email protected]

微信公眾號

文章同步釋出,政採雲技術團隊公眾號,歡迎關注

政採雲技術團隊.png