精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

一文徹底搞透分布式一致性

云計算 分布式
事務一致性。在一個事務內的所有操作,要么全部完成,要么全部不完成,即保證這些操作是對數據的一致更新,避免數據出現不一致的情況。主要通過使用事務保證來實現,例如:關系型數據庫的ACID事務。

分布式系統下的數據一致性可以分為兩大類:

  1. 事務一致性:當多個節點進行操作時,所有節點最終達成的狀態都是一致的。這需要通過協調來保證操作的正確性,避免出現數據不一致的情況;
  2. 副本一致性:數據的多個副本之間保持一致性,這需要保證在對數據進行修改時,所有副本都能夠及時更新,避免數據出現不同步的情況;

定義都比較抽象,舉個例子感受一下:

  1. 事務一致性:電商平臺使用優惠券下單場景:

圖片圖片

  1. 下單成功,優惠券必須處于“已鎖定”狀態;
  2. 支付成功,優惠券必須處于“已使用”狀態;
  3. 訂單取消,優惠券需要恢復為“待使用”狀態;
  4. 優惠券和訂單間就屬于“事務一致”,兩者間存在強關聯關系。
  1. 副本一致性:
  • MySQL 主從復制:是指在主數據庫上進行數據操作后,將這些操作同步到一個或多個從數據庫上。從庫必須與主庫保持同步,以便從庫中的數據和主庫中的數據保持一致;
  • Redis 與 MySQL 一致性:在將 Redis 作為存儲使用時,可以將 MySQL 看做主節點,Redis 看做從節點,當 MySQL 數據發生變更時,自動同步到 Redis 中,并保持數據的一致性;
  1. 圖片image

【注】本文著重介紹 “事務一致性”,多副本一致性,詳見 緩存 或 ES 篇。

1. 脫離數據庫事務的懷抱

在關系型數據庫中,事務(Transaction)是指一組數據庫操作,這些操作要么全部成功要么全部失敗。事務可以保證某些數據操作的一致性,當某一條操作失敗時,會進行回滾,即撤銷已執行的操作,使數據恢復到操作前的狀態。

提到事務一致性,不得不說數據庫事務 ACID:ACID是指數據庫事務的四個關鍵特性,分別為原子性(Atomicity)、一致性(Consistency)、隔離性(Isolation)和持久性(Durability):

  1. 原子性(Atomicity):事務應該被視為一個原子操作,即事務中的所有操作要么全部執行成功,要么全部失敗回滾。如果事務執行過程中出現錯誤,所有修改操作將被回滾撤銷,不會對數據造成損壞;
  2. 一致性(Consistency):事務執行前后,數據應該保持一致狀態。所有數據修改操作都必須確保數據庫的約束條件、觸發器等規則不會被破壞,保持數據完整性;
  3. 隔離性(Isolation):多個事務同時對同一數據進行操作時,事務之間應該相互隔離,互不干擾。數據庫系統應該確保在并發情況下,事務的執行結果和串行執行的結果一致;
  4. 持久性(Durability):事務完成后,其對數據庫所作的所有修改都應該被永久保存,即使系統崩潰或重啟后,修改的數據也應該是可用的;

銀行轉賬應用程序就是典型的 ACID 模型的應用場景。假設用戶A要向用戶B轉賬1000元,轉賬過程就是一個事務,具有原子性、一致性、隔離性和持久性四大特性:

  1. 原子性:轉賬過程總共涉及兩個操作:從A賬戶中減去1000元,向B賬戶中加上1000元。如果這兩個操作中的任何一個失敗,整個事務都將失敗回滾;
  2. 一致性:轉賬前后所有賬戶的余額總和應該是不變的,不會出現余額不足或超額的情況;
  3. 隔離性:如果同時發起兩個轉賬事務,應該確保每個事務只訪問自己的數據,不會互相干擾;
  4. 持久性:一旦轉賬完成,更改數據的事務就必須寫入磁盤,保證即使系統崩潰或重啟后,這些數據仍然是可用的;

數據庫事務絕對是程序員的一大利器,但由于各種原因,這把利器離我們越來越遠:

  1. 負載的挑戰:隨著業務的快速增長,數據庫中的數據量或負載也會達到單一實例的上線,此時,我們:

垂直拆分:將不同的表放到不同的數據庫實例,比如拆分出 User 實例,Order 實例;

圖片圖片

水平拆分:數據量超過單表最大容量時,將數據分拆到不同的數據庫,比如 Order-1 實例、Order-2 實例;

圖片圖片

垂直+水平拆分:先進行垂直拆分,在進行水平拆分;

圖片圖片

  1. 微服務的挑戰:微服務已經成為系統的事實架構,特別是 Spring Boot 和 Spring Cloud 的流行:

微服務的“自治”要求每個微服務都應該有自己的獨立數據存儲,避免與其他服務共享數據存儲,從而降低服務之間的耦合性;

微服務間通過服務發現、負載均衡等方式,將服務之間的關系解耦,從而使得每個服務都具備獨立的自治性;

圖片圖片

不管觸發哪一種條件,都會產生跨數據庫事務,從而增加系統設計的難度。

2. 常見一致性保障機制

針對該問題前人已經提出來多種應對方案,特別是關系型數據庫。

2.1. MySQL事務一致性

熟悉 MySQL 實現的伙伴知道,MySQL 是通過 Redo log 和 Undo log 來實現事務一致性的:

  1. Redo Log:Redo Log 記錄了事務對數據庫所作的修改,包括插入、更新、刪除等操作,它在事務提交前就被寫入磁盤。如果出現故障導致系統崩潰,MySQL 會從 Redo Log 中恢復數據;
  2. Undo Log:Undo Log 記錄了事務對數據庫所作的修改的「前置操作」,并且在事務回滾時用來撤銷事務所做的修改。當事務執行更新時,MySQL 會先將修改前的數據存儲到 Undo Log 中,當事務需要回滾時,MySQL 會根據 Undo Log 中的記錄將數據還原為修改前的狀態。

具體的如下圖所示:

圖片圖片

從圖中可知:

  1. 每一個 DML 語句都會為其生成對應的 Redo log 和 Undo log。

Redo log 記錄正向修改;

Undo log 記錄逆向恢復;

  1. 事務提交應用全部 Redolog 以持久化正向修改;
  2. 事務回滾應用全部 Undolog 以逆向恢復;

其中,可以看出存在兩個核心流程:

  1. 向前補償:redo log 記錄了事務執行的過程,以及事務提交前的數據修改,可以通過重做日志來恢復數據,實現向前補償;
  2. 向后補償:undo log 記錄了事務執行過程中對數據的修改,可以用于回滾事務,實現向后補償;

除了兩種補償機制外,還涉及一個重要的組件“補償管理器”,用于對補償機制進行統一協調。

2.2. 2PC 和 XA

2PC(Two-Phase Commit)和XA是分布式事務中常用的協議和接口:

  • 2PC是分布式事務協議,用于在分布式系統中協調多個參與者的事務提交或回滾。它包括兩個階段:準備階段和提交階段,參與者在準備階段告知協調者它們是否可以正常提交,如果都能正常提交,則在提交階段所有參與者都提交事務。如果有一個參與者無法正常提交,則所有參與者都需要回滾;
  • XA是一組應用程序接口(API),它使應用程序能夠參與分布式事務,并與事務管理器協同工作,以保證事務的一致性。XA接口包括三個接口:XA Transactions、XA Resource、XA Resource Manager,用于實現分布式事務的協調和管理。

MySQL 采用了兩階段提交(Two-Phase Commit,簡稱 2PC)協議,保證 Redolog 和 Binlog 間的數據一致性,確保事務在所有相關節點(包括 Redolog 和 Binlog)執行的情況下,要么全部提交成功,要么全部回滾失敗。

2PC只能應用于兩個事務參與者的場景,而XA可以應用于多個事務參與者的場景,具體如圖所示:

圖片圖片

XA 定義了一組接口:

  • XA資源管理器(XA Resource Manager,RM):用于管理分布式事務的資源,如數據庫、消息隊列等;
  • XA事務管理器(XA Transaction Manager,TM):用于協調各個資源管理器的事務處理;
  • XA接口:XA接口允許應用程序參與到分布式事務的協調中,包括開始、提交或回滾事務等操作;

對應的事務提交和回滾流程如下:

  • 應用程序通過XA接口開始一個分布式事務,XA事務管理器為該事務分配一個唯一的全局事務ID;
  • 應用程序使用XA接口將某些操作注冊為分布式事務的一部分,這些操作可以涉及多個XA資源管理器;
  • 當應用程序執行到提交事務的代碼時,XA事務管理器先協調各個XA資源管理器,檢查這些資源管理器是否都能夠提交事務;
  • 如果所有的資源管理器都能夠提交事務,則XA事務管理器向各個資源管理器發送提交事務的請求,并等待它們的響應;
  • 如果其中有任何一個資源管理器不能提交事務,則XA事務管理器向各個資源管理器發送回滾事務的請求,并等待它們的響應;
  • 當所有的資源管理器都響應提交或回滾事務的請求后,XA事務管理器將事務的狀態(提交或回滾)通知給應用程序,并釋放資源。

2PC (包括升級后的 3PC),在事務執行的整個流程中都需要對資源進行鎖定,在分布式環境下將大幅增加系統響應時間,降低整個系統的吞吐,在實際工作中使用的非常少。

2.3. TCC

TCC 是實現分布式事務解決方案的一種有效方法,更是真正應用于實際工作的一大解決方案。

圖片圖片

TCC (try-confirm-cancel) 是一種分布式事務解決方案,它將一個分布式事務拆分成三個過程:

  • Try 操作:嘗試執行分布式事務中的操作,檢查所有參與方是否準備好執行事務。如果準備好,則鎖定資源,等待確認或取消操作;
  • Confirm 操作:確認執行分布式事務中的操作,提交所有參與方的操作。如果有任何錯誤,則回滾所有操作并釋放鎖定的資源;
  • Cancel 操作:取消執行分布式事務中的操作,回滾所有參與方的操作并釋放鎖定的資源;

TCC 的操作流程如下:

  • 應用程序向協調者請求分布式事務,并傳輸所有需要執行的操作;
  • 協調者根據 TCC 的分布式事務處理策略創建一個唯一的分布式事務 ID,并將它分配給每個參與方;
  • 各參與方執行 Try 操作,并鎖定需要訪問的資源;
  • 協調者檢查所有參與方是否準備好執行操作,如果所有參與方都準備好,則進入 Confirm 階段;
  • Confirm 階段中,各參與方確認執行操作,并將結果提交給協調者;
  • 如果有任何錯誤,協調者將回滾所有操作并釋放鎖定的資源。否則,所有參與方之間的事務將得到確認執行,釋放資源并關閉事務;
  • 如果任何參與方在 Try 階段失敗,則進入 Cancel 階段;
  • Cancel 階段中,各參與方撤銷所有操作并釋放鎖定的資源;
  • 協調者記錄每個階段的操作,以便處理異常情況;

TCC 是一種補償型事務機制,通過人工干預來處理異常,本身具備極佳的靈活性,適用于各種不同類型的應用場景。

2.4. 事務一致性本質

看了不少一致性解決方案,不知道有沒有發現一些規律?

核心組件基本一致:

  • 應用程序:簡單理解為開發的應用系統,借助事務管理器和資源管理的的能力,完成事務一致性保障;
  • 事務管理器:事務的協調者,接收應用程序的請求,對多個資源管理器進行協調,共同完成正向補償和逆向補償;
  • 資源管理器:單一資源管理者,對外提供正向補償接口和逆向補充接口,供應用程序和事務管理器使用;

核心流程基本一致:

  • 正向補償:應用流程向前推進,最終從一個狀態變化為另一個狀態;
  • 逆向補償:應用流程向后推進,將所有操作進行回滾,使其恢復到前一狀態;

簡單來說:事務一致性就是通過協調各個參與節點來實現分布式事務的提交或回滾,確保所有涉及到的操作,要么全部執行成功,要么全部不執行。不同的實現方式只是不同的工具,其實現思路基本一致。

3. 業務一致性保障機制

前人已經為我們提供足夠多的工具,如何更好的使用這些工具,就需要對業務場景進行深入分析。

業務系統一致性是指在多個系統或不同的環境中,不同用戶或系統操作所產生的數據在邏輯上是相同的。它的本質是確保在任何情況下,不同系統或用戶產生的數據都是一致的,并且在系統中的所有操作都是以預期方式進行的。業務系統一致性是確保數據的準確性和可靠性的關鍵因素,可以有效地避免數據錯誤和丟失,提高業務系統的可用性和可靠性,保障企業的持續發展。\\如下圖所示:

圖片圖片

如果可重試性事務間不存在依賴關系,可以并行執行,具體如下:

圖片圖片

在一個復雜的業務流程中,可以將事務分為三類:

  • 關鍵性事務:指的是系統中最為關鍵的一步操作,如果事務提交失敗,則進行回滾操作;如果事務提交成功,則成為事實,無法回滾;
  • 可補償性事務:指的是在關鍵性事務之前的事務操作,通常提供正向和逆向兩組操作,正向操作失敗或關鍵事務失敗,在會逆序調用逆向接口,以對操作進行回滾;
  • 可重試性事務:指的是關鍵事務之后的事務操作,關鍵事務提交成功,則事實已定,下游通過重試的方式完成事務;

我們以分布式系統中的下單流程為例:

圖片圖片

  • 關鍵性事務:就是下單操作,將用戶的信息保存到數據庫。保存失敗,對已經操作的庫存和優惠券進行逆向恢復;保存成功,通過重試保障下游事務的一致性;
  • 可補償性事務:指的是優惠券和庫存服務提供的正向和逆向操作,正向操作可以通過逆向操作進行恢復;
  • 可重試性事務:指的是添加自動取消任務、保存操作日志、發送 MQ,當訂單數據保存成功后,這三者通過不斷重試保障最終都會執行;

3.1. 關鍵性事務

關鍵性事務:指在分布式系統中,只有當某個事務被成功提交后,整個系統才能認為這個事務是成功的。如果這個事務失敗了,那么整個系統就會回滾到之前的狀態。例如支付、訂單提交等。

從關鍵性事務的使用場景出發,最適合的工具便是關系數據庫的事務保障。

圖片圖片

  • 事務提交成功:整個流程向前補償,推動可重試性事務通過不斷重試最終完成業務邏輯;
  • 事務提交失敗:觸發整個流程回滾,逆序調用可補償事務的回滾接口恢復狀態;

3.2. 可補償事務

可補償事務指在某些業務操作中,如果其中一些子操作執行失敗,可以由后續補償操作進行補救,達到一定的業務目的,例如在資金交易中,如果賬戶余額不足而支付子操作失敗,可以通過撤銷訂單等補償操作來保障交易的正確性。

對于可補償事務,需要提供兩組操作:

  1. 正向:標準的業務操作,比如庫存鎖定
  2. 逆向:針對正向操作的恢復操作,比如釋放鎖定庫存
3.2.1. Seata

Seata 是一個開源的分布式事務解決方案,旨在解決分布式系統中的事務一致性問題。在傳統的分布式系統中,由于各個服務之間的數據交互和操作都是獨立進行的,因此很容易出現數據不一致的情況。這會導致系統出現各種異常情況,如數據丟失、重復提交等,從而影響系統的穩定性和可靠性。

Seata 提供了多種解決方案來解決分布式事務一致性問題。其中包括 XA 模式、TCC 模式和 SAGA 模式等。

  • XA 模式是一種基于數據庫的事務管理模式,Seata 通過與數據庫進行交互來實現分布式事務的一致性。該模式適用于對數據一致性要求比較高的業務場景,如金融、電商等。但是,由于需要與數據庫進行交互,因此該模式的性能相對較低;
  • AT模式(基于應用層的兩階段提交方式):AT模式實現在應用程序中嵌入事務語義,通過協調維護必要的鎖,實現多個業務節點之間跨多個數據庫表的事務。適用于關系型數據庫的應用場景,如電商下單等。
  • TCC 模式是一種基于補償的事務管理模式,Seata 通過預留資源、嘗試執行、確認執行和回滾執行四個階段來實現分布式事務的一致性。該模式適用于對性能要求比較高的業務場景,如游戲、社交等。但是,由于需要進行多次異步通信,因此該模式的復雜度較高;
  • SAGA 模式是一種基于事件驅動的事務管理模式,Seata 通過將一個大的分布式事務拆分成多個小的本地事務,并通過異步消息傳遞來實現分布式事務的一致性。該模式適用于對性能和可用性要求比較高的業務場景,如微服務架構下的系統。但是,由于需要進行多次異步通信和狀態管理,因此該模式的復雜度也較高。

Seata 還提供了一些重要的功能,如事務日志記錄、故障恢復、動態擴展等,使得用戶可以更加方便地使用該框架來解決分布式事務一致性問題。同時,Seata 還具有高性能、高可用性和易用性等特點,可以滿足各種不同場景下的需求。

【注】感興趣的話,可以找下 seata 的官方文檔。

3.2.2. Context + Rollback

Seata 雖好,但中間件的引入將大幅提升系統的復雜性,對于一些不太嚴謹的場景或者一些運維能力不足的小團隊可以自己實現回滾方案。

整體方案如下:

圖片圖片

  • 創建一個 Context 對象,用于保存整個流程的上下文數據。其中存在一個 List<RollbackEntry> 屬性,維護待回滾任務列表;
  • 每操作完一個正向流程,向 Context 中注冊一個逆向回調,及 Rollback 任務;
  • 如果

關鍵事務提交成功,Context 注冊的 RollbackEntry 便失去意義;

關鍵事務提交失敗,調用 Context 的 fireFallback 方法進行逆向補償,fireFallback 方法逆向調用注冊的回滾方法,從而恢復業務狀態

該方案基于內存實現,存在失靈的情況,不建議使用在嚴謹的場景。

3.3. 可重試性事務

可重試型事務指在業務操作中,如果某些操作由于網絡波動等原因導致失敗,可以通過重新執行這些操作來達到其預期的結果,例如在發送短信驗證碼時,由于網絡狀況不佳而發送失敗,可以重新嘗試發送,直到發送成功為止。

可重試性事務沒有失敗,只有成功,哪怕是短暫的失敗也會通過不限的重試使其最終達到成功狀態。

3.3.1. @Retry

@Retry 是 Spring 框架提供的一個注解,用于在方法調用失敗時自動進行重試。

通過 @Retry  注解,我們可以定義重試的次數、間隔時間和異常類型等信息,從而實現更可靠的方法調用。

具體來說,@Retry 注解可以通過以下屬性來配置:

  • maxAttempts:最大重試次數;
  • value:重試間隔時間的數值表示;
  • fixedDelay:是否固定等待重試間隔時間后再進行下一次嘗試;
  • backoffPolicy:重試間隔時間的退避策略;
  • allowCoreThreadTimeOut:是否允許在核心線程上進行超時等待;
  • excludeExceptions:需要排除的異常類型;
  • excludeClassNames:需要排除的類名列表;
  • loggerMessage:日志輸出格式;
  • fallbackMethodName:當所有重試都失敗后,執行的方法名稱;

我們看下具體的使用:

  • 基于計數器的重試實現
@Retryable(value = {Exception.class}, maxAttempts = 3, backoff = @Backoff(delay = 1000))
public void doSomething() throws Exception {
    // 業務邏輯代碼
}

該實現會在方法調用失敗時進行最多3次的重試,每次重試之間會等待1秒的時間。如果超過3次重試仍然失敗,則拋出異常。

  • 基于自定義異常處理的重試實現
@Retryable(value = {Exception.class}, maxAttempts = 3, backoff = @Backoff(delay = 1000), fallback = @Fallback(fallbackMethod = "doDefault"))
public void doSomething() throws Exception {
    // 業務邏輯代碼
}

private String doDefault(Exception e) {
    // 當出現指定異常時,執行該方法進行重試處理
}

該實現會在方法調用失敗時進行最多3次的重試,每次重試之間會等待1秒的時間。如果超過3次重試仍然失敗,則會執行 doDefault 方法來進行重試處理。在該方法中,我們可以自定義處理方式來處理異常情況。

@Retry 仍舊是一個內存解決方案,在極端場景下可能出現任務丟失的情況。因此在實際工作中,很少用于可重試性事務這種場景。

3.3.2. MQ

MQ(消息隊列)消費者重試機制是指在消費消息時,如果消費者無法成功消費消息(比如網絡異常、服務器故障等原因),會自動重試一定次數或間隔一定時間后再次嘗試消費消息,以保證消息的可靠性和可用性。

如下圖所示:

圖片im

具有MQ的可重試性事務,需要以下保障:

  • 保障業務操作與消費發送之間的一致性:業務操作成功,消息必須發送成功;業務操作失敗,消息不能發送;
  • 保障消息投遞和消費消費之間的一致性:對于消費失敗的消息,MQ 會自動進行重試,直至消費成功;

一般情況下會采用多次投遞的方式來實現消息投遞和消息消費之間的一致性,所以消息消費者需要保障冪等性,避免多次投遞造成的業務問題。

3.3.2.1. 半消息

RocketMQ事務消息是一種支持分布式事務的消息模型,將消息生產和消費與業務邏輯綁定在一起,確保消息發送和事務執行的原子性,保證消息的可靠性。

事務消息分為兩個階段:發送消息和確認消息,確認消息分為提交和回滾兩個操作。在提交操作執行完畢后,消息才會被消費端消費,而在回滾操作執行完畢后,消息會被刪除,從而達到了事務的一致性和可靠性。

事務消息的發生流程如下:

圖片圖片

  • 生產者發送prepare消息到RocketMQ服務端,RocketMQ將消息存儲到本地并返回結果;
  • 生產者開始執行本地事務,并根據本地事務的結果將狀態信息提交給RocketMQ服務端;
  • 如果本地事務執行成功,生產者向RocketMQ服務端發送commit消息;
  • 如果本地事務執行失敗,生產者向RocketMQ服務端發送rollback消息;
  • RocketMQ接收到commit或rollback消息后,對消息進行投放或刪除;

如果生成者發送 prepare 消息后,未在規定時間內發送 commit 或 rollback 消息,RocketMQ 將進入恢復流程,具體如下:

圖片圖片

  • 如果在回查的時間之前沒有收到相應的 commit 或 rollback 消息,則 RocketMQ 會將對該 prepare 消息進行回查;
  • 應用程序接收到回查指令,從業務庫中獲取數據,并根據業務邏輯進行判斷,最終是 commit 還是 rollback;
  • RocketMQ 接收到 commit 或 rollback 回復后,進行相應動作,從而實現業務操作和消息發送的一致性;

使用 RocketMQ 的事務消息代碼示例如下:

// 編寫事務監聽器類
public class TransactionListenerImpl implements TransactionListener {
    private AtomicInteger transactionIndex = new AtomicInteger(0);

    // 執行本地事務
    public LocalTransactionState executeLocalTransaction(Message msg, Object arg) {
        int value = transactionIndex.getAndIncrement();
        System.out.println("executeLocalTransaction " + value);
        // TODO 執行本地事務,并返回事務狀態
        // 本例假定 index 為偶數的消息執行成功,奇數的消息執行失敗
        if (value % 2 == 0) {
            return LocalTransactionState.COMMIT_MESSAGE;
        }
        return LocalTransactionState.ROLLBACK_MESSAGE;
    }

    // 檢查本地事務狀態
    public LocalTransactionState checkLocalTransaction(MessageExt msg) {
        System.out.println("checkLocalTransaction " + msg.getTransactionId());
        // 模擬檢查本地事務狀態,返回事務狀態
        boolean committed = prepare(true);
        if (committed) {
            return LocalTransactionState.COMMIT_MESSAGE;
        }
        return LocalTransactionState.UNKNOW;
    }

    // 模擬操作預處理邏輯
    private boolean prepare(boolean commit) {
        System.out.println("prepare " + (commit ? "commit" : "rollback"));
        return commit;
    }

}

// 編寫發送消息的代碼
public class Producer {
    private static final String NAME_SERVER_ADDR = "localhost:9876";

    public static void main(String[] args) throws Exception {
        TransactionMQProducer producer = new TransactionMQProducer("MyGroup");
        producer.setNamesrvAddr(NAME_SERVER_ADDR);
        // 注冊事務監聽器
        producer.setTransactionListener(new TransactionListenerImpl());
        producer.start();

        // 發送事務消息
        String[] tags = {"TagA", "TagB", "TagC"};
        for (int i = 0; i < 3; i++) {
            Message msg = new Message("TopicTest", tags[i], ("Hello RocketMQ " + i).getBytes(StandardCharsets.UTF_8));
            // 在消息發送時傳遞給事務監聽器的參數
            SendResult sendResult = producer.sendMessageInTransaction(msg, null);
            System.out.printf("%s%n", sendResult);
        }

        // 關閉生產者
        producer.shutdown();
    }
}

單看代碼很難理解,簡單畫了張圖,具體如下:

圖片圖片

其核心部分就是 TransactionListener 實現,其他部分與正常的消息發送基本一致,TransactionListener 主要完成:

  • 執行本地事務,也就是業務操作;
  • 執行結果檢測,通過反查業務數據,決定消息的后續處理策略;

為了使用事務消息,我們不得不在TransactionListener中編寫進行大量的適配邏輯,增加研發成本,同時由于邏輯被拆分到多處,也增加了代碼的理解成本。

事務消息存在一定的問題:

  • 與 MQ 實現強相關,并不是每個 MQ 實現都對事務消息提供支持;
  • API 比較晦澀,存在一定的學習成本,同時需要對業務邏輯拆分到 Listener 中,增加理解成本;

有沒有實用性強、使用簡單的方案,那可以使用 事務消息表 方案。

3.3.2.2. 事務消息表

事務消息表方案是一種常用的保證消息發送與業務操作一致性的方法。該方案基于數據庫事務和消息隊列,將消息發送和業務操作放入同一個事務中,并將業務操作和消息發送的狀態記錄在數據庫的消息表中,以實現消息的可靠性和冪等性。

如下圖所示:

圖片圖片

核心流程如下:

  • 應用程序開啟一個數據庫事務,并在事務中執行業務操作和消息發送;
  • 在事務中,將業務操作和消息發送的狀態記錄到消息表中;
  • 如果業務操作執行成功,并且消息發送成功,提交事務,否則回滾事務;
  • 定時掃描消息表,并根據消息狀態重新發送未被確認的消息。如果消息發送成功,更新消息狀態;否則根據重試次數更新消息狀態或者丟棄消息;

通過事務消息表方案,可以保證消息的可靠性和冪等性。即使在消息發送失敗或應用程序崩潰的情況下,也可以通過重新發送消息將業務操作和消息發送的狀態同步。同時,該方案可以避免消息重復發送和漏發的情況。

作為一種通用解決方案,lego 對其進行支持,可參考 reliable-message 模塊。

4. 業務補償

不管在設計時使用哪種方案,都是在盡力降低不一致出現的概率,但可怕的是不一致問題終究會發生。

是不是有些奇怪,做了這么多還是無法從根源上徹底解決一致性問題,在實際工作中就是這樣:

  • 并不是所有的可補償事務都能回滾成功:在正向流程中我們都會對資源進行鎖定,如果其他操作破壞了鎖定資源或者破壞了準入條件,程序將無法正常回滾,必須人工介入進行解決。比如,生單時成功鎖定優惠券,但超管發現優惠券發放錯誤對其進行回收,在進行優惠券回滾時,由于優惠券處于不可用狀態,導致無法正常回滾;
  • 并不是所有的可重試事務都能重試成功:業務執行到可重試事務,只能證明其滿足關鍵事務之前的條件,并不一定滿足下游可重試事務的條件。比如,支付成功后需要給用戶發送微信消息,但用戶授權信息已經過期導致消息無法發送;
  • 業務迭代引入 bug 會破壞事務機制:這個就更常見了,由于bug導致流程錯誤,不得不修復問題和數據

除了主動降低不一致性概率,還需要添加一些被動保護機制,也就是常說的業務補償。

4.1. 查詢模式

查詢模型是最常用的一種方式,主要用于應對網絡傳輸中的第三態問題。

第三態指的是在分布式系統中,在進行跨網絡調用時,調用方無法確定被調用方的狀態是否改變了,因為這兩者之間存在一段未知而不可控的網絡延遲時間,導致調用方無法立即得到被調用方的結果。這種情況下,第三態可以看做是一個未知的狀態,需要通過一些機制來解決這個問題。

圖片圖片

當網絡調用出現第三態時,最簡單的方式便是對不確定的狀態進行查詢,如上圖所示:

  • 調用方調用服務完成業務操作,如果成功拿到執行結果,則直接進行后續流程;
  • 如果發生網絡超時,將通過狀態查詢接口來檢查之前的操作是否完成,如果:

已完成,則繼續執行后續流程;

未完成,在重新發起業務調用;

RocketMQ 的事務消息便是基于該機制進行實現。

4.2. 任務檢測模式

當一個業務操作完成后,需要處理多個后續任務,為了保障所有任務都會被執行,可以使用該模式。

如下圖所示:

圖片圖片

image

  • 業務操作后,將業務變更和檢測任務在同一事務保護下進行入庫;
  • 系統繼續執行后續任務,執行完成后對任務狀態進行更新;
  • 系統周期性對超時未執行的任務進行加載,并進行檢測,如果

已經執行,則更新任務狀態

如果未執行,則觸發任務執行

本地消息表就是基于該模式進行構建。

4.3. 對賬模式

對賬模式經常出現在與銀行等金融機構對接的場景。

圖片圖片

業務對賬思路非常簡單:

  • 從不同的業務系統獲取對賬數據;
  • 按照規則進行雙向對賬,如果

一致,則說明系統一致

不一致,進行報警,人工介入進行處理

必須是雙向對賬,單向對賬會出現數據丟失情況。

5. 小結

一致性是分布式系統面臨的巨大挑戰,根據不同場景可以將一致性分為:

  • 事務一致性。在一個事務內的所有操作,要么全部完成,要么全部不完成,即保證這些操作是對數據的一致更新,避免數據出現不一致的情況。主要通過使用事務保證來實現,例如:關系型數據庫的ACID事務。
  • 副本一致性。各個副本之間的數據保持一致。當數據發生變化時,需要將這個變化同步到所有的副本中。主要使用副本同步技術來實現,例如MySQL的主從復制、MySQL 到 Redis的數據同步;

本文重點對事務一致性進行全方位的闡述,包括:

  • 技術視角,常見的解決方案:

MySQL 實現

2PC和XA協議

TCC 解決方案

  • 業務視角,將不同的事務進行分類,以便更好的解決:
  • 關鍵事務
  • 可補償性事務
  • 可重試性事務

有了這些方案后,很多場景下仍需落地業務補充,常見方案包括:

  • 查詢模型
  • 任務檢查模式
  • 對賬模型
責任編輯:武曉燕 來源: geekhalo
相關推薦

2020-10-28 11:15:24

EPaxos分布式性算法

2024-05-27 10:42:55

2020-07-24 13:54:54

分布式一致性技術

2019-10-11 23:27:19

分布式一致性算法開發

2021-11-22 16:30:30

分布式一致性分布式系統

2019-09-05 08:43:34

微服務分布式一致性數據共享

2024-04-10 10:34:34

Cache系統GPU

2017-09-21 10:59:36

分布式系統線性一致性測試

2024-11-28 10:56:55

2022-06-07 12:08:10

Paxos算法

2021-07-28 08:39:25

分布式架構系統

2021-06-03 15:27:31

RaftSOFAJRaft

2017-09-04 14:46:10

分布式事務問題

2020-01-02 09:06:23

微服務數據框架

2021-06-06 12:45:41

分布式CAPBASE

2017-09-22 12:08:01

數據庫分布式系統互聯網

2020-05-11 10:30:57

2PC分布式協議

2021-06-16 08:33:02

分布式事務ACID

2018-03-19 09:50:50

分布式存儲系統

2021-08-13 11:50:23

AnalyticDB 分布式數據庫
點贊
收藏

51CTO技術棧公眾號

91精品网站| 色偷偷噜噜噜亚洲男人| 午夜精品在线观看| 一级特级黄色片| 51av在线| 中文字幕日本乱码精品影院| 91视频婷婷| 五月激情六月丁香| 日韩啪啪电影网| 精品国产91洋老外米糕| 久草在在线视频| 18av在线播放| 久久久久久久电影| 3d动漫啪啪精品一区二区免费| 国产成人在线观看网站| 国产视频网站一区二区三区| 亚洲电影一区二区三区| 亚洲精品人成| 香蕉视频911| 狠狠干成人综合网| 91精品国产福利在线观看| 日韩中字在线观看| 日本欧美在线视频免费观看| av网站免费线看精品| 国产欧洲精品视频| 五月天综合激情| 一区二区三区四区日韩| 亚洲天堂av在线播放| 美女被爆操网站| 成人在线高清| 中文字幕在线一区| 精品欧美国产| 国产黄色免费大片| 日本中文一区二区三区| 97人人模人人爽人人喊中文字| 男人的午夜天堂| 激情综合网站| 日韩精品视频在线| 中文字幕人妻熟女在线| 国内精品视频| 欧美日韩国产综合一区二区三区| 欧美国产激情视频| 国产在线xxx| 亚洲精品ww久久久久久p站| 亚洲福利av在线| 国产在线播放av| 91在线视频免费91| 国产成人精品在线视频| 国产精品第56页| 欧美日韩ab| 美女少妇精品视频| 亚洲熟女www一区二区三区| 欧美欧美在线| 欧美人与z0zoxxxx视频| 一区二区三区国产免费| 日韩成人高清| 在线欧美日韩精品| 99草草国产熟女视频在线| 中文在线а√在线8| 天天免费综合色| 色综合av综合无码综合网站| 男人天堂视频在线观看| 亚洲成人动漫一区| 国产特级淫片高清视频| 玖玖在线播放| 日韩欧美一区二区三区久久| 成人毛片视频网站| 91涩漫在线观看| 丁香天五香天堂综合| 91麻豆蜜桃| 天堂国产一区二区三区| 91在线国产观看| 欧美精品久久久| 91免费视频播放| 老色鬼精品视频在线观看播放| 国产日韩欧美自拍| 国产乱淫a∨片免费观看| 国产精品综合久久| 欧美一区二区三区四区在线| 国产小视频在线免费观看| 国产亚洲午夜| 国产精品福利网站| 久久久久久久久久综合 | 新67194成人永久网站| 欧美在线一级va免费观看| 91黑人精品一区二区三区| 男女性色大片免费观看一区二区 | 久久综合九色综合88i| 性欧美freesex顶级少妇| 欧美中文字幕不卡| 深夜福利网站在线观看| 亚洲激情77| 日日骚久久av| 日本熟妇成熟毛茸茸| 爽好多水快深点欧美视频| 成人中文字幕在线观看| aaa在线视频| 精品一区二区三区视频在线观看| 国产高清一区视频| 精品三级久久久久久久电影聊斋| 亚洲欧洲日产国产综合网| 国产欧美日韩网站| 国产精品第一国产精品| 欧美xxxx老人做受| 国产精品理论在线| 亚洲清纯自拍| 成人欧美在线观看| 日韩精品系列| 一区二区三区四区国产精品| 久草在在线视频| 国产精品对白久久久久粗| 欧美一区二区三区白人| 中文字幕在线观看网址| 亚洲人成免费网站| 国产成人精品av| 天堂av中文字幕| 亚洲日本在线a| 国产成人精品视频ⅴa片软件竹菊| 欧美三级一区| 色视频www在线播放国产成人| 国产精品99re| 国内久久精品视频| 婷婷久久五月天| 日本а中文在线天堂| 欧美成人vr18sexvr| 天堂网av2018| 视频一区二区三区入口| 国产精成人品localhost| 欧美私人网站| 一区二区三区中文在线观看| 国产aaaaa毛片| 亚洲人成网www| 久久久久久久色| 国产三级三级在线观看| 国产精品久久久久久亚洲毛片 | 欧洲高清一区二区| 日本黄色免费在线| 亚洲国产精品久久久久秋霞不卡| 强行糟蹋人妻hd中文| 精品一区二区在线播放| 中国人体摄影一区二区三区| 成人h在线观看| 伊人久久精品视频| 日本精品入口免费视频| 国产日韩精品一区二区三区| 97视频在线免费播放| 亚洲v天堂v手机在线| 91av在线影院| 天堂中文字幕在线| 亚洲一卡二卡三卡四卡| 久久人妻少妇嫩草av蜜桃| 欧美日韩精品免费观看视频完整| 91精品在线观| 超碰在线无需免费| 69精品人人人人| av成人免费网站| 国产乱一区二区| 日本免费成人网| 爱爱精品视频| 日韩视频不卡| 91gao视频| 成人影院www在线观看| 91精品婷婷国产综合久久| √天堂中文官网8在线| 精品一区免费av| 在线视频一区观看| 欧美成人精品一级| 久久青草福利网站| 青青草在线播放| 色爱区综合激月婷婷| 在线观看亚洲色图| 天天精品视频| 国产精品一区二区免费| 成人黄色免费短视频| 日韩久久精品一区| 日本少妇全体裸体洗澡| 91看片淫黄大片一级| 中文字幕在线观看第三页| 欧美丰满日韩| 国产精品一区二区三区不卡| 日韩电影大全网站| 久久精品视频在线| 国 产 黄 色 大 片| 国产精品无码永久免费888| 在线免费黄色网| 伊人久久大香线蕉综合热线 | 老司机午夜性大片| 欧美大片专区| 免费观看成人高| 欧美xxx黑人xxx水蜜桃| 精品亚洲国产成av人片传媒| 中文在线观看av| 久久久美女毛片| 亚洲欧美aaa| 在线一区视频| 在线日韩av永久免费观看| 国产精品15p| 国产精品视频地址| 国产精品国精产品一二| 在线观看亚洲视频| 免费看黄色一级视频| 欧美性videosxxxxx| 精品无码人妻一区二区三| 欧美激情在线一区二区三区| 熟女人妻一区二区三区免费看| 国产精品亚洲欧美| 4444在线观看| 精品国产欧美日韩| 国产伦精品一区二区| 亚洲欧洲二区| 国产高清在线不卡| 丁香花在线观看完整版电影| 最近中文字幕2019免费| 天堂网av2014| 精品国一区二区三区| 亚洲最大成人在线视频| 色综合中文字幕国产| 免费无码毛片一区二区app| 国产精品久久久久久久久免费桃花| 亚洲少妇18p| 国产精品一区一区三区| 天天操天天爽天天射| 美女诱惑一区| 亚洲激情图片| 免费欧美一区| 精品国产乱码久久久久| 午夜视频一区二区在线观看| 国产伊人精品在线| 中文字幕系列一区| 欧美在线xxx| 天堂av中文在线观看| 欧美高跟鞋交xxxxhd| www视频在线免费观看| 日韩在线观看网址| av一区在线观看| 一区二区欧美在线| 国产三级在线观看| 亚洲女人天堂成人av在线| 午夜国产在线视频| 亚洲国产一区二区三区在线观看 | 91色.com| 男男一级淫片免费播放| 成人免费不卡视频| 97精品人人妻人人| 成人综合在线观看| 91porn在线| 成人av网站在线| 黄色污在线观看| kk眼镜猥琐国模调教系列一区二区| 中文字幕在线国产| 国产98色在线|日韩| 国产免费a级片| 99re热视频精品| 日韩精品卡通动漫网站| 青娱乐精品在线视频| jizz欧美激情18| 男男成人高潮片免费网站| 五月婷婷深爱五月| 六月丁香综合在线视频| 亚洲涩涩在线观看| 国产乱码精品1区2区3区| 亚洲区 欧美区| 99久久免费精品| 欧美做受高潮6| 国产欧美va欧美不卡在线| 国产精品麻豆一区| 91视频精品在这里| 无码h肉动漫在线观看| 国产日本亚洲高清| 中文字幕91视频| 一区二区三区自拍| 精品美女久久久久| 欧美天堂亚洲电影院在线播放| 一区不卡在线观看| 精品久久久久久久久久久久包黑料 | 国产成人精品亚洲日本在线桃色| 国产午夜伦鲁鲁| 老司机午夜精品视频在线观看| 香蕉视频禁止18| 国产精品资源在线看| 朝桐光av一区二区三区| 国产亚洲婷婷免费| 黄色a级片在线观看| 精品欧美一区二区三区| 一级黄色片在线| 精品国产91亚洲一区二区三区婷婷| 欧美日本韩国一区二区| 美日韩在线视频| 欧美羞羞视频| 91精品免费| 成人激情诱惑| 免费毛片网站在线观看| 美日韩一区二区| 妖精视频一区二区| 国产精品理论片在线观看| 亚洲国产精一区二区三区性色| 欧美系列日韩一区| 蜜桃视频久久一区免费观看入口| 在线播放国产一区二区三区| 欧美xxx黑人xxx水蜜桃| 国产精品久久色| 乱中年女人伦av一区二区| 麻豆中文字幕在线观看| 久久精品91| av免费观看不卡| 国产精品国模大尺度视频| 91porny在线| 日韩精品一区二区在线| av男人的天堂在线| 欧美怡春院一区二区三区| 免费观看亚洲天堂| 四虎永久国产精品| 国产精品一区亚洲| 9191在线视频| 国产精品超碰97尤物18| 国产www在线| 精品国产不卡一区二区三区| 欧洲不卡av| 国产精品久久久久久久天堂| 女同一区二区三区| 99久久免费观看| 亚洲国产裸拍裸体视频在线观看乱了中文| 天天碰免费视频| 久久亚洲精精品中文字幕早川悠里| 免费一级a毛片夜夜看| 欧美久久一二区| 亚洲av无码乱码国产精品| 中文综合在线观看| 男人皇宫亚洲男人2020| 国外成人免费视频| 狠狠色综合网| 高清中文字幕mv的电影| 一区二区成人在线| 五月婷婷色丁香| 亚洲精品mp4| 第一av在线| 国产精品久久久久免费| 国产精品扒开腿做爽爽爽软件| 国产女同无遮挡互慰高潮91| 国产精品久久久久久久久免费相片| 中文字幕视频免费观看| 中文字幕亚洲图片| 久久精品嫩草影院| 国产不卡一区二区三区在线观看| 久久久久国产精品| 亚洲三级在线视频| 亚洲情趣在线观看| 国产乱淫av片免费| 久久成人av网站| 日韩激情欧美| 蜜臀av色欲a片无码精品一区| 国产成a人无v码亚洲福利| 69精品久久久| 日韩精品视频三区| 午夜无码国产理论在线| 五月天丁香综合久久国产| 老司机午夜精品| 欧美黑吊大战白妞| 精品国产人成亚洲区| 欧美调教sm| 日韩av电影免费在线观看| 日韩av网站免费在线| 69夜色精品国产69乱| 日韩亚洲欧美综合| www.youjizz.com在线| 国产综合色香蕉精品| 中文视频一区| 国产白嫩美女无套久久| 色妞www精品视频| 日本综合在线| 国产精品日韩高清| 羞羞答答国产精品www一本| 夜夜春很很躁夜夜躁| 欧美一区二区三区影视| www在线看| 日韩wuma| 国产精品综合av一区二区国产馆| 精品久久免费视频| 亚洲性生活视频在线观看| 精品午夜av| a√天堂在线观看| 成人免费在线播放视频| 亚洲精品久久久久久久久久久久久久 | 欧美电影免费提供在线观看| 欧美激情网站| 国产系列第一页| 99国产精品久久久久久久久久久| 五月婷婷激情五月| 欧美理论电影在线播放| 黄色日韩网站| 久久这里只有精品8| 国产日本欧洲亚洲| 蜜桃91麻豆精品一二三区| 国产精品观看在线亚洲人成网| 欧美暴力喷水在线| 精品无码人妻一区二区免费蜜桃| 日韩区在线观看| 欧美日韩国产网站| 国产 日韩 亚洲 欧美| 国产精品美女一区二区在线观看|