Spring Cloud同步場景分散式事務怎樣做?試試Seata

  • 2019 年 10 月 3 日
  • 筆記

file

一、概述

在微服務架構下,雖然我們會盡量避免分散式事務,但是只要業務複雜的情況下這是一個繞不開的問題,如何保證業務數據一致性呢?本文主要介紹同步場景下使用Seata的AT模式來解決一致性問題。

Seata是 阿里巴巴 開源的 一站式分散式事務解決方案 中間件,以 高效 並且對業務 0 侵入 的方式,解決 微服務 場景下面臨的分散式事務問題

 

二、Seata介紹

整體事務邏輯是基於 兩階段提交 的模型,核心概念包括以下3個角色:

  • TM:事務的發起者。用來告訴 TC,全局事務的開始,提交,回滾。
  • RM:具體的事務資源,每一個 RM 都會作為一個分支事務註冊在 TC。
  • TC:事務的協調者seata-server,用於接收我們的事務的註冊,提交和回滾。

目前的Seata有兩種模式可使用分別對應不同業務場景

2.1. AT模式

該模式適合的場景:

  • 基於支援本地 ACID 事務的關係型資料庫。
  • Java 應用,通過 JDBC 訪問資料庫。

file

 
一個典型的分散式事務過程:

  1. TM 向 TC 申請開啟一個全局事務,全局事務創建成功並生成一個全局唯一的 XID。
  2. XID 在微服務調用鏈路的上下文中傳播。
  3. RM 向 TC 註冊分支事務,將其納入 XID 對應全局事務的管轄。
  4. TM 向 TC 發起針對 XID 的全局提交或回滾決議。
  5. TC 調度 XID 下管轄的全部分支事務完成提交或回滾請求。

 

2.2. MT模式

該模式邏輯類似TCC,需要 自定義實現 prepare、commit和rollback的邏輯,適合 非關係型資料庫 的場景

file

 

三、Seata場景樣例

模擬一個簡單的用戶下單場景,4個子工程分別是 Bussiness(事務發起者)、Order(創建訂單)、Storage(扣減庫存) 和 Account(扣減賬戶餘額)

file

3.1. 部署Seata的Server端

file

Discover註冊、Config配置和Store存儲模組默認都是使用file只能適用於單機,我們安裝的時候分別改成使用nacos和Mysql以支援server端集群

3.1.1. 下載最新版本並解壓

https://github.com/seata/seata/releases

 

3.1.2. 修改 conf/registry.conf 配置

註冊中心和配置中心默認是file這裡改為nacos;設置 registry 和 config 節點中的type為nacos,修改serverAddr為你的nacos節點地址。

registry {    type = "nacos"      nacos {      serverAddr = "192.168.28.130"      namespace = "public"      cluster = "default"    }  }    config {    type = "nacos"      nacos {      serverAddr = "192.168.28.130"      namespace = "public"      cluster = "default"    }  }

 

3.1.3. 修改 conf/nacos-config.txt配置

file

  • 修改 service.vgroup_mapping 為自己應用對應的名稱;如果有多個服務,添加相應的配置

    默認組名為${spring.application.name}-fescar-service-group,可通過spring.cloud.alibaba.seata.tx-service-group配置修改

  • 修改 store.mode 為db,並修改資料庫相關配置

 

3.1.4. 初始化seata的nacos配置

cd conf  sh nacos-config.sh 192.168.28.130

成功後在nacos的配置列表中能看到seata的相關配置

file

 

3.1.5. 初始化資料庫

執行conf/db_store.sql中的腳本

 

3.1.6. 啟動seata-server

sh bin/seata-server.sh -p 8091 -h 192.168.28.130

 

3.2. 應用配置

3.2.1. 初始化資料庫

執行腳本 seata-demo.sql

需在業務相關的資料庫中添加 undo_log 表,用於保存需要回滾的數據

 

3.2.2. 添加registry.conf配置

直接把 seata-server 中的registry.conf複製到每個服務中去即可,不需要修改
file

 

3.2.3. 修改配置

demo中的每個服務各自修改配置文件

  • bootstrap.yml 修改nacos地址
  • application.yml 修改資料庫配置

 

3.2.4. 配置數據源代理

Seata是通過代理數據源實現分散式事務,所以需要配置io.seata.rm.datasource.DataSourceProxy的Bean,且是@Primary默認的數據源,否則事務不會回滾,無法實現分散式事務

public class DataSourceProxyConfig {      @Bean      @ConfigurationProperties(prefix = "spring.datasource")      public DruidDataSource druidDataSource() {          return new DruidDataSource();      }        @Primary      @Bean      public DataSourceProxy dataSourceProxy(DruidDataSource druidDataSource) {          return new DataSourceProxy(druidDataSource);      }  }

因為使用了mybatis的starter所以需要排除DataSourceAutoConfiguration,不然會產生循環依賴

@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})

 

3.2.5. 事務發起者添加全局事務註解

事務發起者 business-service 添加 @GlobalTransactional 註解

@GlobalTransactional  public void placeOrder(String userId) {      ......  }

 

3.3. 測試

提供兩個介面測試

  1. 事務成功:扣除庫存成功 > 創建訂單成功 > 扣減賬戶餘額成功
    http://localhost:9090/placeOrder
  2. 事務失敗:扣除庫存成功 > 創建訂單成功 > 扣減賬戶餘額失敗,事務回滾
    http://localhost:9090/placeOrderFallBack

 

3.4. demo下載地址

https://gitee.com/zlt2000/microservices-platform/tree/master/zlt-demo/seata-demo

 

推薦閱讀

 
掃碼關注有驚喜!

file

Tags: