分布式事務解決方案(三)

在Java分布式系統領域,傳統強一致性方案(如2PC、3PC)在高并發、復雜業務場景下暴露出性能瓶頸和阻塞問題。而Saga模式與事件溯源(Event Sourcing)作為更具彈性和擴展性的解決方案,逐漸成為分布式事務處理和數據管理的主流選擇。本文將深入探討這兩種方案的核心原理、Java實現方式及其在實際場景中的應用實踐。

一、Saga模式

1.1 Saga模式核心思想

Saga模式將一個分布式事務拆分為多個本地事務,每個本地事務對應一個Saga子事務。Saga通過兩種恢復策略保證最終一致性:

  • 向后恢復:當某子事務失敗時,依次調用所有已執行子事務的補償操作(反向操作),撤銷整個事務。
  • 向前恢復:重試失敗的子事務,適用于必須成功的業務場景(如訂單支付)。

1.2 示例場景:電商訂單全流程處理

以電商場景中“創建訂單-扣減庫存-鎖定優惠券-支付”流程為例,展示Saga模式的實現。

1.2.1 子事務與補償接口定義

// 訂單服務接口
public interface OrderService {void createOrder(String orderId);  // 正向操作void cancelOrder(String orderId);  // 補償操作
}// 庫存服務接口
public interface StockService {void deductStock(String orderId, int quantity);void revertStock(String orderId, int quantity);
}// 優惠券服務接口
public interface CouponService {void lockCoupon(String orderId, String couponId);void unlockCoupon(String orderId, String couponId);
}// 支付服務接口
public interface PaymentService {void processPayment(String orderId, BigDecimal amount);void refundPayment(String orderId, BigDecimal amount);
}

1.2.2 Saga編排器實現

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;@Component
public class OrderSagaOrchestrator {@Autowiredprivate OrderService orderService;@Autowiredprivate StockService stockService;@Autowiredprivate CouponService couponService;@Autowiredprivate PaymentService paymentService;public void executeSaga(String orderId, int quantity, BigDecimal amount, String couponId) {try {// 步驟1:創建訂單orderService.createOrder(orderId);// 步驟2:扣減庫存stockService.deductStock(orderId, quantity);// 步驟3:鎖定優惠券couponService.lockCoupon(orderId, couponId);// 步驟4:處理支付paymentService.processPayment(orderId, amount);} catch (Exception e) {// 向后恢復:發生異常時執行補償操作rollbackSaga(orderId, quantity, couponId);throw new RuntimeException("Saga execution failed", e);}}private void rollbackSaga(String orderId, int quantity, String couponId) {try {paymentService.refundPayment(orderId, null);couponService.unlockCoupon(orderId, couponId);stockService.revertStock(orderId, quantity);orderService.cancelOrder(orderId);} catch (Exception ex) {// 補償失敗時記錄日志并人工介入System.err.println("Saga rollback failed: " + ex.getMessage());}}
}

1.3 Saga模式的實現方式

  • 協同式Saga:通過事件驅動,子事務完成后發布事件觸發下一個子事務(如使用Kafka或Spring Cloud Stream)。
  • 編排式Saga:由中央Saga編排器(如上述代碼)按順序調用子事務,并負責補償邏輯。

1.4 優缺點與適用場景

  • 優點:高可用性、低侵入性、適用于長事務;
  • 缺點:部分場景下數據存在短暫不一致,補償邏輯復雜;
  • 適用場景:電商訂單流程、金融風控審批、物流調度等長周期業務。

二、事件溯源

2.1 事件溯源核心概念

事件溯源(Event Sourcing)是一種數據持久化模式,它不直接存儲業務對象的最終狀態,而是記錄所有導致狀態變更的事件。通過重放事件流,系統可以重建任何時間點的業務狀態。核心要素包括:

  • 事件:不可變的業務事實(如OrderCreatedEventPaymentCompletedEvent);
  • 事件存儲:用于持久化事件的數據庫(如MongoDB、EventStoreDB);
  • 狀態投影:通過事件流實時或定期計算出的業務狀態。

2.2 示例場景:銀行賬戶交易系統

2.2.1 事件定義

import java.math.BigDecimal;
import java.time.LocalDateTime;// 事件基類
public abstract class AccountEvent {private String eventId;private LocalDateTime timestamp;public AccountEvent() {this.eventId = java.util.UUID.randomUUID().toString();this.timestamp = LocalDateTime.now();}// Getters and setters...
}// 存款事件
public class DepositEvent extends AccountEvent {private BigDecimal amount;public DepositEvent(BigDecimal amount) {this.amount = amount;}// Getters and setters...
}// 取款事件
public class WithdrawalEvent extends AccountEvent {private BigDecimal amount;public WithdrawalEvent(BigDecimal amount) {this.amount = amount;}// Getters and setters...
}

2.2.2 事件存儲與狀態重建

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;// 事件存儲接口
public interface EventStore {void append(String aggregateId, AccountEvent event);List<AccountEvent> getEvents(String aggregateId);
}// 內存實現示例
public class InMemoryEventStore implements EventStore {private final List<AccountEvent> events = new ArrayList<>();@Overridepublic void append(String aggregateId, AccountEvent event) {events.add(event);}@Overridepublic List<AccountEvent> getEvents(String aggregateId) {return events.stream().filter(e -> aggregateId.equals(e.getAggregateId())).collect(Collectors.toList());}
}// 賬戶狀態投影
public class AccountProjection {private BigDecimal balance = BigDecimal.ZERO;public void apply(AccountEvent event) {if (event instanceof DepositEvent) {DepositEvent deposit = (DepositEvent) event;balance = balance.add(deposit.getAmount());} else if (event instanceof WithdrawalEvent) {WithdrawalEvent withdrawal = (WithdrawalEvent) event;balance = balance.subtract(withdrawal.getAmount());}}public BigDecimal getBalance() {return balance;}
}

2.3 與CQRS的結合應用

事件溯源常與CQRS(命令查詢職責分離)結合:

  • 寫模型:接收命令并生成事件,存入事件存儲;
  • 讀模型:通過事件流生成狀態投影,供查詢接口使用。

2.4 優缺點與適用場景

  • 優點:數據可追溯性強、支持審計與回放、高并發寫入性能;
  • 缺點:查詢性能依賴投影優化,復雜業務的事件設計難度高;
  • 適用場景:審計系統、金融交易記錄、游戲日志、實時數據分析等。

三、Saga與事件溯源:方案對比

維度Saga模式事件溯源
核心目標解決分布式事務最終一致性實現數據可追溯性與狀態重建
數據存儲傳統數據庫存儲業務狀態事件日志 + 狀態投影
一致性類型最終一致性最終一致性(查詢端)
強一致性(事件追加)
性能特點適合長事務處理,補償邏輯影響性能高并發寫入,查詢性能依賴投影優化
典型應用跨服務業務流程協調審計追蹤、實時分析、歷史狀態查詢

四、總結

Saga模式和事件溯源為Java分布式系統提供了更靈活的事務處理和數據管理思路。在實際項目中:

  • 復雜業務流程:優先采用Saga模式,通過補償機制保障最終一致性;
  • 需要歷史追溯的場景:選擇事件溯源,結合CQRS提升讀寫性能;
  • 混合架構:將Saga用于事務協調,事件溯源用于關鍵業務的數據記錄與分析。

通過深入理解這兩種方案的設計哲學與實現細節,開發者能夠構建出更具彈性、可擴展性和可維護性的分布式系統。


本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/88100.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/88100.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/88100.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【時時三省】(C語言基礎)通過指針引用數組

山不在高&#xff0c;有仙則名。水不在深&#xff0c;有龍則靈。 ----CSDN 時時三省數組元素的指針一個變量有地址&#xff0c;一個數組包含若干元素&#xff0c;每個數組元素都在內存中占用存儲單元&#xff0c;它們都有相應的地址。指針變量既然可以指向變量&#xff0c;當然…

【WEB】Polar靶場 21-25題 詳細筆記

二十一.php very nicephp又是你 ,但是經過這么多次折磨后我感覺我已經有一點抗性了老規矩&#xff0c;先看知識點PHP 序列化是將 PHP 變量&#xff08;如對象、數組&#xff09;轉換為字符串的過程&#xff0c;便于存儲或傳輸。反序列化則是將字符串還原為原始變量。這在緩存、…

【Guava】1.0.設計虛擬機的方向

【Guava】1.0.設計虛擬機的方向虛擬機是什么&#xff1f;棧式虛擬機棧式虛擬機的優缺點題外話虛擬機是什么&#xff1f; 虛擬機&#xff08;VirtualMachine, VM&#xff09;是一種計算機程序或系統&#xff0c;它通過軟件模擬物理計算機的硬件運行環境&#xff0c;使得多個操作…

[附源碼+數據庫+畢業論文]基于Spring+MyBatis+MySQL+Maven+jsp實現的高校實驗室資源綜合管理系統,推薦!

摘 要 現代經濟快節奏發展以及不斷完善升級的信息化技術&#xff0c;讓傳統數據信息的管理升級為軟件存儲&#xff0c;歸納&#xff0c;集中處理數據信息的管理方式。本高校實驗室資源綜合管理系統就是在這樣的大環境下誕生&#xff0c;其可以幫助管理者在短時間內處理完畢龐大…

Spring Boot:影響事務回滾的幾種情況

一、Controller 捕獲異常導致事務失效 需求 我們有一個用戶注冊服務&#xff0c;注冊時需要&#xff1a; 創建用戶賬戶分配初始積分發送注冊通知 這三個操作需要在同一個事務中執行&#xff0c;任何一步失敗都要回滾。 錯誤示例&#xff1a;Controller 捕獲異常導致事務失效 Re…

如何避免分布式爬蟲被目標網站封禁?

在分布式爬蟲的大規模數據采集場景中&#xff0c;避免被目標網站封禁的核心邏輯是&#xff1a;通過技術手段模擬真實用戶行為&#xff0c;降低爬蟲行為的可識別性&#xff0c;同時建立動態適配機制應對網站反爬策略的升級。以下從請求偽裝、行為控制、資源管理、反爬對抗四個維…

Maven 打包排除特定依賴的完整指南(詳細方法 + 示例)

前言 在使用 Maven 構建 Java 項目時&#xff0c;我們常常需要對項目的打包過程進行精細化控制&#xff0c;尤其是希望排除某些特定的依賴庫。這可能是為了減小最終構建產物的體積、避免版本沖突&#xff0c;或者僅僅是為了滿足不同環境下的部署需求。 本文將詳細介紹如何在 Ma…

Terraform `for_each` 精講:優雅地自動化多域名證書驗證

大家好&#xff0c;在云原生和自動化運維的世界里&#xff0c;Terraform無疑是基礎設施即代碼&#xff08;IaC&#xff09;領域的王者。它強大的聲明式語法讓我們能夠輕松地描述和管理云資源。然而&#xff0c;即使是經驗豐富的工程師&#xff0c;在面對某些動態場景時也可能會…

C++標準庫中各種互斥鎖的用法 mutex

示例 僅供參考學習 #include <mutex> #include <shared_mutex> #include <thread> #include <chrono> #include <iostream> #include <vector>// // 1. std::mutex - 基本互斥鎖 // void basic_mutex_example() {std::mutex mtx;int cou…

Android Handler機制與底層原理詳解

Android 的 Handler 機制是跨線程通信和異步消息處理的核心框架&#xff0c;它構成了 Android 應用響應性和事件驅動模型的基礎&#xff08;如 UI 更新、后臺任務協調&#xff09;。其核心思想是 “消息隊列 循環處理”。 核心組件及其關系Handler (處理器): 角色: 消息的發送…

jQuery JSONP:實現跨域數據交互的利器

jQuery JSONP&#xff1a;實現跨域數據交互的利器 引言 隨著互聯網的發展&#xff0c;跨域數據交互的需求日益增加。在Web開發中&#xff0c;由于同源策略的限制&#xff0c;直接通過XMLHttpRequest請求跨域數據會遇到諸多問題。而JSONP&#xff08;JSON with Padding&#xff…

Redis集群和 zookeeper 實現分布式鎖的優勢和劣勢

在分布式系統中&#xff0c;實現分布式鎖是確保多個節點間互斥訪問共享資源的一種常見需求。Redis 集群 和 zookeeper 都可以用來實現這一功能&#xff0c;但它們有著各自不同的優勢和劣勢。 CAP 理論&#xff1a; 在設計一個分布式系統時&#xff0c;一致性&#xff08;Consis…

如何備份vivo手機中的聯系人?

隨著vivo移動設備在全球設立7個研發中心&#xff0c;vivo正在進入更多的國家。如今&#xff0c;越來越多的人開始使用vivo手機。以vivo X100為例&#xff0c;它配備了主攝像頭和多個輔助攝像頭&#xff0c;提供多樣化的拍攝選項&#xff0c;并搭載了最新的FunTouch OS&#xff…

python腳本編程:使用BeautifulSoup爬蟲庫獲取熱門單機游戲排行榜

BeautifulSoup是一個便捷的解析html頁面元素的python庫&#xff0c;此處用來寫一個簡單的爬蟲批量抓取國內游戲資訊網站的近期熱門單機游戲排行榜。 網頁來源如下所示代碼 from bs4 import BeautifulSoup import requests# get web page web_url "https://www.3dmgame.co…

C#配置全面詳解:從傳統方式到現代配置系統

C#配置全面詳解&#xff1a;從傳統方式到現代配置系統 在軟件開發中&#xff0c;配置是指應用程序運行時可調整的參數集合&#xff0c;如數據庫連接字符串、API 地址、日志級別等。將這些參數從代碼中分離出來&#xff0c;便于在不修改代碼的情況下調整應用行為。C# 提供了多種…

數據中臺架構解析:湖倉一體的實戰設計

目錄 一、數據中臺與湖倉一體架構是什么 1. 數據中臺 2. 湖倉一體架構 3. 湖倉一體在數據中臺里的價值 二、湖倉一體架構的核心部件 1. 數據湖 2. 數據倉庫 3. 數據集成工具 4. 數據分析與處理引擎 三、湖倉一體架構實戰設計 1. 需求分析與規劃 2. 數據湖建設 3. …

SQL Server表分區技術詳解

表分區概述 表分區是將大型數據庫表物理分割為多個較小單元的技術,邏輯上仍表現為單一實體。該技術通過水平分割數據顯著提升查詢性能,尤其針對TB級數據表可降低90%的響應時間。典型應用場景包含訂單歷史表、日志記錄表等具有明顯時間特征的業務數據,以及需要定期歸檔的審計…

WHIP(WebRTC HTTP Ingestion Protocol)詳解

WHIP&#xff08;WebRTC HTTP Ingestion Protocol&#xff09;詳解 WHIP&#xff08;WebRTC HTTP Ingestion Protocol&#xff09;是一種基于 HTTP 的協議&#xff0c;用于將 WebRTC 媒體流推送到媒體服務器&#xff08;如 SRS、Janus、LiveKit&#xff09;。它是為簡化 WebRT…

圖像噪點消除:用 OpenCV 實現多種濾波方法

在圖像處理中&#xff0c;噪點是一個常見的問題。它可能是由于圖像采集設備的缺陷、傳輸過程中的干擾&#xff0c;或者是光照條件不佳引起的。噪點會影響圖像的質量和后續處理的效果&#xff0c;因此消除噪點是圖像預處理的重要步驟之一。本文將介紹如何使用 OpenCV 實現幾種常…

AI的Prompt提示詞:英文寫好還是中文好?

在與AI人大模型交互時,Prompt(提示詞)的質量直接決定了輸出的精準度和有效性。一個常見的問題是:究竟是用英文寫Prompt好,還是用中文寫更好?這并非一個簡單的二元選擇,而是涉及到語言模型的底層邏輯、表達的精確性以及個人使用習慣的綜合考量。 英文Prompt的優勢 模型訓…