溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Seata如何搭建與分布式事務入門

發布時間:2021-07-06 18:14:11 來源:億速云 閱讀:284 作者:chen 欄目:編程語言
# Seata如何搭建與分布式事務入門

## 目錄
1. [分布式事務基礎概念](#一分布式事務基礎概念)
   - 1.1 [什么是分布式事務](#11-什么是分布式事務)
   - 1.2 [CAP理論與BASE理論](#12-cap理論與base理論)
   - 1.3 [常見解決方案對比](#13-常見解決方案對比)
2. [Seata核心架構解析](#二seata核心架構解析)
   - 2.1 [TC/TA/RM角色劃分](#21-tctarm角色劃分)
   - 2.2 [AT模式原理詳解](#22-at模式原理詳解)
   - 2.3 [TCC/SAGA模式對比](#23-tccsaga模式對比)
3. [Seata Server部署實戰](#三seata-server部署實戰)
   - 3.1 [單機版部署指南](#31-單機版部署指南)
   - 3.2 [高可用集群配置](#32-高可用集群配置)
   - 3.3 [注冊中心與配置中心](#33-注冊中心與配置中心)
4. [Spring Cloud集成實踐](#四spring-cloud集成實踐)
   - 4.1 [Spring Boot Starter配置](#41-spring-boot-starter配置)
   - 4.2 [數據源代理配置](#42-數據源代理配置)
   - 4.3 [全局事務注解使用](#43-全局事務注解使用)
5. [生產環境優化建議](#五生產環境優化建議)
   - 5.1 [參數調優指南](#51-參數調優指南)
   - 5.2 [常見問題排查](#52-常見問題排查)
   - 5.3 [監控與告警配置](#53-監控與告警配置)
6. [實戰案例演示](#六實戰案例演示)
   - 6.1 [電商下單場景](#61-電商下單場景)
   - 6.2 [跨行轉賬場景](#62-跨行轉賬場景)

## 一、分布式事務基礎概念

### 1.1 什么是分布式事務

在單體應用架構中,我們通常使用本地事務(如MySQL的InnoDB引擎事務)來保證數據一致性。但當系統演進為微服務架構時,一個業務操作往往需要跨多個服務、多個數據庫,這就產生了分布式事務需求。

**典型場景示例**:
```java
// 偽代碼展示分布式事務場景
@DistributedTransactional
public void createOrder(OrderDTO order) {
    // 操作1:庫存服務扣減庫存
    inventoryService.reduceStock(order.getItems());
    
    // 操作2:訂單服務創建訂單
    orderService.create(order);
    
    // 操作3:賬戶服務扣減余額
    accountService.debit(order.getUserId(), order.getAmount());
}

1.2 CAP理論與BASE理論

CAP定理(布魯爾定理)

  • 一致性(Consistency):所有節點訪問同一份最新數據
  • 可用性(Availability):每次請求都能獲取非錯誤響應
  • 分區容錯性(Partition tolerance):系統在網絡分區時仍能運行

分布式系統必須滿足P,因此在C和A之間需要權衡。Seata采用的AT模式優先保證AP,最終達到C。

BASE理論

  • Basically Available:基本可用
  • Soft state:軟狀態
  • Eventually consistent:最終一致

1.3 常見解決方案對比

方案 原理 優點 缺點
2PC 兩階段提交 強一致性 同步阻塞、單點問題
TCC Try-Confirm-Cancel 高靈活性 開發復雜度高
SAGA 長事務拆分 適合長流程 無隔離性
本地消息表 異步確保型 簡單可靠 時效性差
Seata AT 反向SQL補償 零侵入、高性能 全局鎖競爭

二、Seata核心架構解析

2.1 TC/TA/RM角色劃分

Seata如何搭建與分布式事務入門

  • Transaction Coordinator (TC):事務協調器(Server端)
  • Transaction Manager ™:定義事務邊界(@GlobalTransactional)
  • Resource Manager (RM):管理分支事務(數據源代理)

2.2 AT模式原理詳解

階段一:業務數據+回滾日志入庫

-- 原始SQL
UPDATE product SET stock = stock - 1 WHERE id = 1001;

-- Seata代理后實際執行
-- 1. 查詢前鏡像
SELECT stock FROM product WHERE id = 1001;
-- 2. 執行業務SQL
UPDATE product SET stock = stock - 1 WHERE id = 1001;
-- 3. 查詢后鏡像
SELECT stock FROM product WHERE id = 1001;
-- 4. 插入undo_log
INSERT INTO undo_log VALUES(...);

階段二提交流程: 1. TM向TC發起全局提交 2. TC異步刪除各分支undo_log

階段二回滾流程: 1. TM向TC發起全局回滾 2. TC查詢undo_log構造補償SQL

UPDATE product SET stock = stock + 1 WHERE id = 1001;

2.3 TCC/SAGA模式對比

TCC模式開發示例

public interface AccountService {
    @TwoPhaseBusinessAction(name = "debit", commitMethod = "confirm", rollbackMethod = "cancel")
    boolean tryDebit(@BusinessActionContextParameter(paramName = "userId") String userId,
                    @BusinessActionContextParameter(paramName = "money") BigDecimal money);
    
    boolean confirm(BusinessActionContext context);
    boolean cancel(BusinessActionContext context);
}

模式選擇建議

  • AT:適合大部分CRUD場景
  • TCC:需要高隔離性的金融場景
  • SAGA:長流程業務(如機票預定)

三、Seata Server部署實戰

3.1 單機版部署指南

步驟1:下載安裝包

wget https://github.com/seata/seata/releases/download/v1.5.2/seata-server-1.5.2.tar.gz
tar -zxvf seata-server-1.5.2.tar.gz

步驟2:修改conf/registry.conf

registry {
  type = "nacos"
  nacos {
    serverAddr = "127.0.0.1:8848"
    namespace = ""
    cluster = "default"
  }
}

步驟3:啟動服務

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

3.2 高可用集群配置

數據庫存儲模式配置(conf/file.conf)

store {
  mode = "db"
  db {
    datasource = "druid"
    dbType = "mysql"
    url = "jdbc:mysql://127.0.0.1:3306/seata"
    user = "root"
    password = "123456"
    minConn = 5
    maxConn = 30
  }
}

需要初始化的數據庫表

-- 全局事務表
CREATE TABLE IF NOT EXISTS global_table (
  xid VARCHAR(128) NOT NULL PRIMARY KEY,
  ...
);
-- 分支事務表
CREATE TABLE IF NOT EXISTS branch_table (
  branch_id BIGINT NOT NULL PRIMARY KEY,
  xid VARCHAR(128) NOT NULL,
  ...
);

3.3 注冊中心與配置中心

Nacos配置中心同步: 1. 將config.txt上傳到Nacos

python3 nacos-config.py -h 127.0.0.1 -p 8848 -g SEATA_GROUP -t 5a3c7d6c-f497-4d68-a71a-2e5e1230

四、Spring Cloud集成實踐

4.1 Spring Boot Starter配置

pom.xml依賴

<dependency>
    <groupId>io.seata</groupId>
    <artifactId>seata-spring-boot-starter</artifactId>
    <version>1.5.2</version>
</dependency>
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-seata</artifactId>
</dependency>

application.yml配置

seata:
  application-id: order-service
  tx-service-group: my_tx_group
  service:
    vgroup-mapping:
      my_tx_group: default
  registry:
    type: nacos
    nacos:
      server-addr: 127.0.0.1:8848

4.2 數據源代理配置

必須配置項

@Configuration
public class DataSourceConfig {
    
    @Bean
    @ConfigurationProperties(prefix = "spring.datasource")
    public DruidDataSource druidDataSource() {
        return new DruidDataSource();
    }

    @Primary
    @Bean("dataSource")
    public DataSource dataSource(DruidDataSource druidDataSource) {
        return new DataSourceProxy(druidDataSource);
    }
}

4.3 全局事務注解使用

基礎用法

@GlobalTransactional(timeoutMills = 60000, name = "createOrder")
public void createOrder(Order order) {
    // 1. 扣減庫存
    storageFeignService.deduct(order.getCommodityCode(), order.getCount());
    
    // 2. 創建訂單
    orderMapper.insert(order);
    
    // 3. 扣減余額
    accountFeignService.debit(order.getUserId(), order.getMoney());
}

注意事項: 1. 避免在事務方法內處理HTTP請求 2. 超時時間要大于所有分支事務耗時總和 3. 建議在入口Controller方法上聲明

五、生產環境優化建議

5.1 參數調優指南

關鍵server端參數(seata-server/conf/file.conf)

transport {
  thread-factory {
    boss-thread-prefix = "NettyBoss"
    worker-thread-prefix = "NettyServerNIOWorker"
    server-executor-thread-prefix = "NettyServerBizHandler"
    share-boss-worker = false
    client-selector-thread-prefix = "NettyClientSelector"
    client-selector-thread-size = 1
    client-worker-thread-prefix = "NettyClientWorkerThread"
    worker-thread-size = "default"
  }
}

客戶端優化建議

seata:
  client:
    rm-report-success-enable: false # 關閉分支執行結果上報
    report-retry-count: 5          # 重試次數

5.2 常見問題排查

全局鎖沖突處理: 1. 檢查業務SQL條件是否走索引 2. 減少單個事務涉及的數據范圍 3. 適當調整隔離級別:

@GlobalTransactional(lockRetryInternal = 100, lockRetryTimes = 30)

事務懸掛問題: - 現象:分支事務先于全局事務注冊 - 解決方案:升級到1.5.0+版本,開啟:

seata:
  client:
    undo:
      data-validation: true

5.3 監控與告警配置

Prometheus監控配置

metrics {
  enabled = true
  registry-type = "compact"
  exporter-list = "prometheus"
  exporter-prometheus-port = 9898
}

Grafana監控看板: 1. 導入官方Dashboard(ID:10477) 2. 關鍵監控指標: - seata.transaction.active.count - seata.transaction.committed.rate - seata.transaction.rollback.rate

六、實戰案例演示

6.1 電商下單場景

業務流程圖

sequenceDiagram
    participant C as Client
    participant O as OrderService
    participant S as StorageService
    participant A as AccountService
    
    C->>O: 提交訂單
    O->>S: 扣減庫存
    S-->>O: 操作成功
    O->>A: 扣減余額
    A-->>O: 操作成功
    O->>O: 生成訂單
    O-->>C: 下單成功

異常處理設計: 1. 庫存不足:立即返回錯誤 2. 余額不足:觸發全局回滾 3. 網絡超時:依賴重試機制

6.2 跨行轉賬場景

TCC模式實現

// 轉賬服務接口
public interface TransferService {
    @TwoPhaseBusinessAction(name = "transfer", commitMethod = "confirm", rollbackMethod = "cancel")
    boolean tryTransfer(@BusinessActionContextParameter(paramName = "from") String from,
                       @BusinessActionContextParameter(paramName = "to") String to,
                       @BusinessActionContextParameter(paramName = "amount") BigDecimal amount);
}

// 賬戶服務實現
@Service
public class AccountServiceImpl implements AccountService {
    
    @Transactional
    public boolean tryDebit(String accountNo, BigDecimal amount) {
        // 檢查賬戶狀態
        // 凍結部分金額
        accountMapper.freezeAmount(accountNo, amount);
        return true;
    }
    
    public boolean confirm(BusinessActionContext context) {
        // 實際扣減凍結金額
        String accountNo = (String)context.getActionContext("from");
        BigDecimal amount = (BigDecimal)context.getActionContext("amount");
        accountMapper.debit(accountNo, amount);
        accountMapper.unfreezeAmount(accountNo, amount);
        return true;
    }
}

SAGA模式設計

// 狀態機定義示例
{
  "name": "bankTransferSaga",
  "steps": [
    {
      "name": "deductFromAccount",
      "compensate": "compensateDeduct",
      "service": "accountService",
      "input": ["$.['from']", "$.['amount']"]
    },
    {
      "name": "addToAccount",
      "compensate": "compensateAdd",
      "service": "accountService",
      "input": ["$.['to']", "$.['amount']"]
    }
  ]
}

作者建議:在實際項目中使用Seata時,建議從AT模式開始,隨著業務復雜度提升逐步考慮TCC或SAGA模式。同時要特別注意undo_log表的大小控制,建議定期歸檔歷史數據。 “`

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

亚洲午夜精品一区二区_中文无码日韩欧免_久久香蕉精品视频_欧美主播一区二区三区美女