微服務學習(六)之分布式事務

微服務學習(六)之分布式事務

  • 一、認識Seata
  • 二、部署TC服務
    • 1、準備數據庫表
    • 2、準備配置文件
    • 3、docker部署
  • 三、微服務集成seata
    • 1、引入依賴
    • 2、改造配置
    • 3、添加數據庫表
      • 4、測試
  • 四、XA模式
    • 1、兩階段提交
    • 2、seata的XA模型
    • 3、優缺點
    • 4、實現步驟
  • 五、AT模式
    • 1、Seata的AT模型
    • 2、流程梳理
    • 3、AT與XA的區別

首先我們看看項目中的下單業務整體流程:

在這里插入圖片描述
由于訂單、購物車、商品分別在三個不同的微服務,而每個微服務都有自己獨立的數據庫,因此下單過程中就會跨多個數據庫完成業務。而每個微服務都會執行自己的本地事務:

  • 交易服務:下單事務
  • 購物車服務:清理購物車事務
  • 庫存服務:扣減庫存事務

整個業務中,各個本地事務是有關聯的。因此每個微服務的本地事務,也可以稱為分支事務。多個有關聯的分支事務一起就組成了全局事務。我們必須保證整個全局事務同時成功或失敗。
我們知道每一個分支事務就是傳統的單體事務,都可以滿足ACID特性,但全局事務跨越多個服務、多個數據庫,是否還能滿足呢?

事務并未遵循ACID的原則,歸其原因就是參與事務的多個子業務在不同的微服務,跨越了不同的數據庫。雖然每個單獨的業務都能在本地遵循ACID,但是它們互相之間沒有感知,不知道有人失敗了,無法保證最終結果的統一,也就無法遵循ACID的事務特性了。
這就是分布式事務問題,出現以下情況之一就可能產生分布式事務問題:

  • 業務跨多個服務實現
  • 業務跨多個數據源實現

一、認識Seata

解決分布式事務的方案有很多,但實現起來都比較復雜,因此我們一般會使用開源的框架來解決分布式事務問題。在眾多的開源分布式事務框架中,功能最完善、使用最多的就是阿里巴巴在2019年開源的Seata了。

其實分布式事務產生的一個重要原因,就是參與事務的多個分支事務互相無感知,不知道彼此的執行狀態。因此解決分布式事務的思想非常簡單:
就是找一個統一的事務協調者,與多個分支事務通信,檢測每個分支事務的執行狀態,保證全局事務下的每一個分支事務同時成功或失敗即可。大多數的分布式事務框架都是基于這個理論來實現的。

Seata也不例外,在Seata的事務管理中有三個重要的角色:

  • TC (Transaction Coordinator) - 事務協調者:維護全局和分支事務的狀態,協調全局事務提交或回滾。
  • TM (Transaction Manager) - 事務管理器:定義全局事務的范圍、開始全局事務、提交或回滾全局事務。
  • RM (Resource Manager) - 資源管理器:管理分支事務,與TC交談以注冊分支事務和報告分支事務的狀態,并驅動分支事務提交或回滾。

Seata的工作架構如圖所示:

在這里插入圖片描述

其中,TM和RM可以理解為Seata的客戶端部分,引入到參與事務的微服務依賴中即可。將來TM和RM就會協助微服務,實現本地分支事務與TC之間交互,實現事務的提交或回滾。

而TC服務則是事務協調中心,是一個獨立的微服務,需要單獨部署。

二、部署TC服務

1、準備數據庫表

Seata支持多種存儲模式,但考慮到持久化的需要,我們一般選擇基于數據庫存儲。執行課前資料提供的《seata-tc.sql》,導入數據庫表:

在這里插入圖片描述

2、準備配置文件

課前資料準備了一個seata目錄,其中包含了seata運行時所需要的配置文件:

在這里插入圖片描述

其中包含中文注釋,大家可以自行閱讀。
我們將整個seata文件夾拷貝到虛擬機的/root目錄:

在這里插入圖片描述

3、docker部署

需要注意,要確保nacos、mysql都在hm-net網絡中。如果某個容器不再hm-net網絡,可以參考下面的命令將某容器加入指定網絡:

docker network connect [網絡名] [容器名]

在虛擬機的/root目錄執行下面的命令:

docker run --name seata \
-p 8099:8099 \
-p 7099:7099 \
-e SEATA_IP=192.168.150.101 \     		//這里把ip換成自己docker的地址
-v ./seata:/seata-server/resources \
--privileged=true \
--network hm-net \
-d \
seataio/seata-server:1.5.2

三、微服務集成seata

1、引入依賴

為了方便各個微服務集成seata,我們需要把seata配置共享到nacos,因此trade-service模塊不僅僅要引入seata依賴,還要引入nacos依賴:

<!--統一配置管理--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId></dependency><!--讀取bootstrap文件--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-bootstrap</artifactId></dependency><!--seata--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-seata</artifactId></dependency>

2、改造配置

首先在nacos上添加一個共享的seata配置,命名為shared-seata.yaml:

在這里插入圖片描述

內容如下:

seata:registry: # TC服務注冊中心的配置,微服務根據這些信息去注冊中心獲取tc服務地址type: nacos # 注冊中心類型 nacosnacos:server-addr: 192.168.150.101:8848 # nacos地址namespace: "" # namespace,默認為空group: DEFAULT_GROUP # 分組,默認是DEFAULT_GROUPapplication: seata-server # seata服務名稱username: nacospassword: nacostx-service-group: hmall # 事務組名稱service:vgroup-mapping: # 事務組與tc集群的映射關系hmall: "default"

然后,改造trade-service模塊,添加bootstrap.yaml:

在這里插入圖片描述

內容如下:

spring:application:name: trade-service # 服務名稱profiles:active: devcloud:nacos:server-addr: 192.168.150.101 # nacos地址config:file-extension: yaml # 文件后綴名shared-configs: # 共享配置- dataId: shared-jdbc.yaml # 共享mybatis配置- dataId: shared-log.yaml # 共享日志配置- dataId: shared-swagger.yaml # 共享日志配置- dataId: shared-seata.yaml # 共享seata配置

可以看到這里加載了共享的seata配置。
然后改造application.yaml文件,內容如下:

server:port: 8085
feign:okhttp:enabled: true # 開啟OKHttp連接池支持sentinel:enabled: true # 開啟Feign對Sentinel的整合
hm:swagger:title: 交易服務接口文檔package: com.hmall.trade.controllerdb:database: hm-trade

參考上述辦法分別改造hm-cart和hm-item兩個微服務模塊。

3、添加數據庫表

seata的客戶端在解決分布式事務的時候需要記錄一些中間數據,保存在數據庫中。因此我們要先準備一個這樣的表。
將課前資料的seata-at.sql分別文件導入hm-trade、hm-cart、hm-item三個數據庫中:

在這里插入圖片描述

-- for AT mode you must to init this sql for you business database. the seata server not need it.
CREATE TABLE IF NOT EXISTS `undo_log`
(`branch_id`     BIGINT       NOT NULL COMMENT 'branch transaction id',`xid`           VARCHAR(128) NOT NULL COMMENT 'global transaction id',`context`       VARCHAR(128) NOT NULL COMMENT 'undo_log context,such as serialization',`rollback_info` LONGBLOB     NOT NULL COMMENT 'rollback info',`log_status`    INT(11)      NOT NULL COMMENT '0:normal status,1:defense status',`log_created`   DATETIME(6)  NOT NULL COMMENT 'create datetime',`log_modified`  DATETIME(6)  NOT NULL COMMENT 'modify datetime',UNIQUE KEY `ux_undo_log` (`xid`, `branch_id`)
) ENGINE = InnoDBAUTO_INCREMENT = 1DEFAULT CHARSET = utf8mb4 COMMENT ='AT transaction mode undo table';

OK,至此為止,微服務整合的工作就完成了。可以參考上述方式對hm-item和hm-cart模塊完成整合改造。

4、測試

接下來就是測試的分布式事務的時候了。

我們找到trade-service模塊下的com.hmall.trade.service.impl.OrderServiceImpl類中的createOrder方法,也就是下單業務方法。

將其上的@Transactional注解改為Seata提供的 @GlobalTransactional

在這里插入圖片描述

@GlobalTransactional注解就是在標記事務的起點,將來TM就會基于這個方法判斷全局事務范圍,初始化全局事務。

我們重啟trade-service、item-service、cart-service三個服務。再次測試,發現分布式事務的問題解決了!

四、XA模式

Seata支持四種不同的分布式事務解決方案:

  • XA
  • TCC
  • AT
  • SAGA
    這里我們以XA模式和AT模式來給大家講解其實現原理。

XA 規范 是 X/Open 組織定義的分布式事務處理(DTP,Distributed Transaction Processing)標準,XA 規范 描述了全局的TM與局部的RM之間的接口,幾乎所有主流的數據庫都對 XA 規范 提供了支持。

1、兩階段提交

A是規范,目前主流數據庫都實現了這種規范,實現的原理都是基于兩階段提交。

正常情況:

在這里插入圖片描述
異常情況:

在這里插入圖片描述
一階段:

  • 事務協調者通知每個事務參與者執行本地事務
  • 本地事務執行完成后報告事務執行狀態給事務協調者,此時事務不提交,繼續持有數據庫鎖

二階段:

  • 事務協調者基于一階段的報告來判斷下一步操作
  • 如果一階段都成功,則通知所有事務參與者,提交事務
  • 如果一階段任意一個參與者失敗,則通知所有事務參與者回滾事務

2、seata的XA模型

Seata對原始的XA模式做了簡單的封裝和改造,以適應自己的事務模型,基本架構如圖:

在這里插入圖片描述
RM一階段的工作:

  1. 注冊分支事務到TC
  2. 執行分支業務sql但不提交
  3. 報告執行狀態到TC

TC二階段的工作:

  1. TC檢測各分支事務執行狀態
  2. 如果都成功,通知所有RM提交事務
  3. 如果有失敗,通知所有RM回滾事務

RM二階段的工作:

  • 接收TC指令,提交或回滾事務

3、優缺點

XA模式的優點是什么?

  • 事務的強一致性,滿足ACID原則
  • 常用數據庫都支持,實現簡單,并且沒有代碼侵入

XA模式的缺點是什么?

  • 因為一階段需要鎖定數據庫資源,等待二階段結束才釋放,性能較差
  • 依賴關系型數據庫實現事務

4、實現步驟

首先,我們要在配置文件中指定要采用的分布式事務模式。我們可以在Nacos中的共享shared-seata.yaml配置文件中設置:

seata:data-source-proxy-mode: XA

其次,我們要利用@GlobalTransactional標記分布式事務的入口方法:

在這里插入圖片描述

五、AT模式

AT模式同樣是分階段提交的事務模型,不過缺彌補了XA模型中資源鎖定周期過長的缺陷。

1、Seata的AT模型

基本流程圖:

在這里插入圖片描述

階段一RM的工作:

  • 注冊分支事務
  • 記錄undo-log(數據快照)
  • 執行業務sql并提交
  • 報告事務狀態
    階段二提交時RM的工作:
  • 刪除undo-log即可
    階段二回滾時RM的工作:
  • 根據undo-log恢復數據到更新前

2、流程梳理

我們用一個真實的業務來梳理下AT模式的原理。
比如,現在有一個數據庫表,記錄用戶余額:

在這里插入圖片描述
其中一個分支業務要執行的SQL為:

 update tb_account set money = money - 10 where id = 1

AT模式下,當前分支事務執行流程如下:
一階段:

  1. TM發起并注冊全局事務到TC
  2. TM調用分支事務
  3. 分支事務準備執行業務SQL
  4. RM攔截業務SQL,根據where條件查詢原始數據,形成快照。
{"id": 1, "money": 100
}
  1. RM執行業務SQL,提交本地事務,釋放數據庫鎖。此時 money = 90
  2. RM報告本地事務狀態給TC

二階段:

  1. TM通知TC事務結束
  2. TC檢查分支事務狀態
    a. 如果都成功,則立即刪除快照
    b. 如果有分支事務失敗,需要回滾。讀取快照數據({“id”: 1, “money”: 100}),將快照恢復到數據庫。此時數據庫再次恢復為100

流程圖:

在這里插入圖片描述

3、AT與XA的區別

簡述AT模式與XA模式最大的區別是什么?

  • XA模式一階段不提交事務,鎖定資源;AT模式一階段直接提交,不鎖定資源。
  • XA模式依賴數據庫機制實現回滾;AT模式利用數據快照實現數據回滾。
  • XA模式強一致;AT模式最終一致

可見,AT模式使用起來更加簡單,無業務侵入,性能更好。因此企業90%的分布式事務都可以用AT模式來解決。

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

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

相關文章

Go實現用戶登錄小程序

寫一個用戶登錄注冊的小程序 運行程序&#xff0c;給出提示1. 注冊輸入用戶名、密碼、年齡、性別 {"用戶名": "root", "passwd": "123456", "age": 18, "sex": "男"}注冊前要判斷是否存在此用戶2. 登錄…

鴻蒙藍牙通信

https://developer.huawei.com/consumer/cn/doc/best-practices/bpta-bluetooth-low-energy 藍牙權限 module.json5 {"module": {"requestPermissions": [{"name": "ohos.permission.ACCESS_BLUETOOTH","reason": "…

Java:Map

文章目錄Map常用方法Map遍歷的三種方法先獲取Map集合的全部鍵&#xff0c;再通過遍歷來找值Entry對象forEach結合lambda表達式Map 案例分析需求我的代碼&#xff08;不好&#xff09;老師的代碼&#xff08;好&#xff09;好在哪里另外集合分為Collection和MapMap常用方法 代碼…

fastjson2 下劃線字段轉駝峰對象

在對接第三方或查詢數據庫時&#xff0c;返回的字段是下劃線分隔的&#xff0c;而在業務中需要轉成java對象&#xff0c;java對象的字段是駝峰的&#xff0c;使用fastjson2時&#xff0c;有兩種方法可以實現&#xff1a; 比如數據格式是&#xff1a; {"item_id": &q…

【硬件】藍牙音頻協議

1. 無線音頻傳輸的工作原理 在無線傳輸的過程中&#xff0c;音源設備首先將MP3、FLAC等音頻文件還原為PCM格式。通過藍牙音頻編碼轉為藍牙無線傳輸的文件&#xff0c;發送到音頻設備段。將藍牙無線傳輸的文件再次還原為PCM格式&#xff0c;之后轉為模擬信號并放大&#xff0c;通…

【宇樹科技:未來1-3年,機器人可流水線打螺絲】

在第三屆中國國際供應鏈促進博覽會上&#xff0c;宇樹科技工作人員表示&#xff0c;未來1到3年內&#xff0c;機器人產品有望從單一工業化產品&#xff0c;發展至復合化工業場景&#xff0c;如機器人搬完箱子后&#xff0c;換個 “手” 就能在流水線上打螺絲。在3到10年內&…

Spring AI 1.0版本 + 千問大模型之 文本記憶對話

上篇文章&#xff0c;主要是簡單講解了一下文本對話的功能。由于模型不具備上下文記憶功能&#xff0c;只能一問一答。因此我們需要實現記憶對話功能&#xff0c;這樣大模型回答信息才能夠更加準確。 1、pom依賴 項目構建就不詳細說了&#xff0c;大家可以參考上篇 文本對話 文…

測試學習之——Pytest Day2

一、Pytest配置框架Pytest的配置旨在改變其默認行為&#xff0c;以適應不同的測試需求和項目結構。理解其配置層級和常用參數&#xff0c;是高效使用Pytest的基礎。1. 配置的意義與層級配置的本質在于提供一種機制&#xff0c;允許用戶根據項目特點、團隊規范或特定測試場景&am…

Go-Redis × RediSearch 全流程實踐

1. 連接 Redis ctx : context.Background()rdb : redis.NewClient(&redis.Options{Addr: "localhost:6379",Password: "",DB: 0,Protocol: 2, // 推薦 RESP2// UnstableResp3: true, // 若要體驗 RESP3 Raw* })2. 準備示例數據 u…

深入理解指針(指針篇2)

在指針篇1我們已經了解了整型指針&#xff0c;當然還有很多其他類型的指針&#xff0c;像字符指針、數組指針、函數指針等&#xff0c;他們都有他們的特別之處&#xff0c;讓我們接著學習。1. 指針類型介紹和應用1.1 字符指針變量字符指針變量類型為char*&#xff0c;一般這樣使…

Python+Selenium自動化爬取攜程動態加載游記

1. 引言 在旅游行業數據分析、輿情監測或競品研究中&#xff0c;獲取攜程等平臺的游記數據具有重要價值。然而&#xff0c;攜程的游記頁面通常采用動態加載&#xff08;Ajax、JavaScript渲染&#xff09;&#xff0c;傳統的**<font style"color:rgb(64, 64, 64);backg…

ESP8266服務器建立TCP連接失敗AT+CIPSTART=“TCP“,“192.168.124.1“,8080 ERROR CLOSED

1.檢查服務器端口8081是否開啟監聽2.檢查路由項是否被防火墻攔截方法 1&#xff1a;使用 netsh查看防火墻規則?netsh advfirewall firewall show rule nameall dirout | findstr "8081"如果無輸出&#xff0c;說明防火墻未針對該端口設置規則&#xff08;可能默認攔…

Linux 內存管理(2):了解內存回收機制

目錄一、透明大頁1.1 原理1.2 透明大頁的三大優勢1.3 透明大頁控制接口詳解1.4 使用場景與最佳實踐1.5 問題排查與監控1.6 與傳統大頁的對比二、Linux伙伴系統水位機制詳解2.1 三種核心水位詳解2.2 水位在伙伴系統中的實現2.3 水位觸發機制的實際行為2.4 水位關鍵操作接口2.5 水…

前端學習7:CSS過渡與動畫--補間動畫 (Transition) vs 關鍵幀動畫 (Animation)

一、補間動畫&#xff08;Tween Animation&#xff09;vs 關鍵幀動畫&#xff08;Keyframe Animation&#xff09;概念對比表&#xff1a;補間動畫 (Transition)關鍵幀動畫 (Animation)定義元素從初始狀態到結束狀態的過渡效果通過定義多個關鍵幀控制動畫的中間狀態觸發方式需要…

PyTorch 損失函數詳解:從理論到實踐

目錄 一、損失函數的基本概念 二、常用損失函數及實現 1. 均方誤差損失&#xff08;MSELoss&#xff09; 2. 平均絕對誤差損失&#xff08;L1Loss/MAELoss&#xff09; 3. 交叉熵損失&#xff08;CrossEntropyLoss&#xff09; 4. 二元交叉熵損失&#xff08;BCELoss&…

MinIO深度解析:從核心特性到Spring Boot實戰集成

在當今數據爆炸的時代&#xff0c;海量非結構化數據的存儲與管理成為企業級應用的關鍵挑戰。傳統文件系統在TB級數據面前捉襟見肘&#xff0c;而昂貴的云存儲服務又讓中小企業望而卻步。MinIO作為一款開源高性能對象存儲解決方案&#xff0c;正以其獨特的技術優勢成為開發者的首…

騰訊云服務上下載docker以及使用Rabbitmq的流程

執行以下命令&#xff0c;添加 Docker 軟件源并配置為騰訊云源。sudo yum-config-manager --add-repohttps://mirrors.cloud.tencent.com/docker-ce/linux/centos/docker-ce.repo sudo sed -i "s/download.docker.com/mirrors.tencentyun.com\/docker-ce/g" /etc/yu…

UE5 一些關于過場動畫sequencer,軌道track的一些Python操作

刪除多余的軌道 import unreal def execute():movie_scene_actors []sequence_assets []data 0.0# 獲取編輯器實用工具庫lib unreal.EditorUtilityLibrary()selected_assets lib.get_selected_assets()for asset in selected_assets:if asset.get_class() unreal.LevelS…

前端性能優化“核武器”:新一代圖片格式(AVIF/WebP)與自動化優化流程實戰

前端性能優化“核武器”&#xff1a;新一代圖片格式(AVIF/WebP)與自動化優化流程實戰 當你的頁面加載時間超過3秒時&#xff0c;用戶的跳出率會飆升到40%以上。而在所有的前端性能優化手段中&#xff0c;圖片優化無疑是投入產出比最高的一環。一張未經優化的巨大圖片&#xff0…

單元測試學習+AI輔助單測

標題單元測試衡量指標具體測試1、Resource2、MockBean3、Test4、Test模板5、單測示例H2數據庫JSON1、使用方式AI輔助單測使用方法單元測試 單元測試一般指程序員在寫好代碼后&#xff0c;提交測試前&#xff0c;需要驗證自己的代碼是否可以正常工作&#xff0c;同時將自己的代…