Seata Springboot Integrated Seata のインストールから始まる分散トランザクションの旅

Seata のインストールから始まる分散トランザクションのプロセス

ここに画像の説明を挿入

導入

シータとは何ですか?

最新のアプリケーション開発では、分散システムがますます広く使用されています。ただし、システムの複雑さが増すにつれて、分散トランザクションを処理することがますます困難になります。これがシータが登場した背景である。Seata (Simple Extensible Autonomous Transaction Architecture) は、分散システムにおけるトランザクションの一貫性と調整の問題を解決するために設計されたオープンソースの分散トランザクション ソリューションです。
従来のモノリシック アプリケーションでは、通常、トランザクションを管理し、データの一貫性を確保するためにリレーショナル データベースが使用されます。しかし、分散システムでは、複数の独立したサービスが関与するため、トランザクション管理が複雑になります。分散トランザクションの要件は、データの一貫性を維持するために、関連するすべてのサービスが正常にコミットまたはロールバックされることです。

Seata は 2 つの主要なトランザクション モードを提供します。

  1. AT モード (自動補償モード): AT モードでは、Seata は補償ロジックを手動で記述することなく、自動的にトランザクションを補償します。Seata は、トランザクションのすべての操作をグローバル トランザクションに配置し、各ブランチの try 操作を実行し、例外が発生したときに対応する補償操作を実行します。

  2. TCC モード (2 フェーズ コミット モード): TCC モードでは、開発者は試行、確認、キャンセルの 3 つのフェーズのロジックを手動で記述する必要があります。TCC モードでは、Seata がグローバル トランザクションのコミットとロールバックを調整する責任を負い、各ブランチの試行、確認、キャンセルの操作は開発者によって実装されます。

Seata は、スケーラブルなレジストリとストレージのサポートも提供するため、さまざまなシナリオに適しています。

一般に、Seata は強力な分散トランザクション ソリューションであり、開発者が分散トランザクションの問題を解決し、分散システムにおけるデータの一貫性と信頼性を確保するのに役立ちます。Seata を統合することで、開発者は複雑な分散アプリケーションをより簡単に構築し、システムの安定性とパフォーマンスを向上させることができます。

Seata サーバーのインストール

Seata Server リリースをダウンロードする

最新の Seata Server リリースをSeata 公式 Web サイトからダウンロードし、指定したディレクトリに解凍できます。ソース バージョンとバイナリ バージョンがありますが、ここではダウンロードするバイナリ ファイルをインストールすることを選択します。私のバージョンは 1.7.0 (2023-07-11、推奨バージョン)
ここに画像の説明を挿入

Seata の構成

ファイルを解凍する

ここに画像の説明を挿入
ダウンロードしたファイルはzipファイルで、解凍すると上記のフォルダになります、デフォルトのフォルダ名はseataです。

Seataのymlファイルを設定する

seata/confディレクトリに入ると、ここには 2 つの構成ファイルがあります。application.yml任意に名前を変更し、application.example.ymlそれをapplication.ymlメインの構成ファイルとして変更する必要があります。
ここに画像の説明を挿入
ファイルを変更しますapplication.yml。ここでは登録センターとして nacos を使用しているため、変更する必要がある場所は次のとおりです。

  1. シート:構成:タイプ
  2. シート:レジストリ:タイプ
  3. ストア:モード
  4. ストア:セッション:モード
  5. ストア:ロック:モード
  6. store:db データベースの構成が独自に変更されます

設定ファイル:

server:
  port: 7091

spring:
  application:
    name: seata-server

logging:
  config: classpath:logback-spring.xml
  file:
    path: ${
    
    user.home}/logs/seata
  extend:
    logstash-appender:
      destination: 127.0.0.1:4560
    kafka-appender:
      bootstrap-servers: 127.0.0.1:9092
      topic: logback_to_logstash
# 这里是主要的配置文件
seata:
  config:
    # support: nacos 、 consul 、 apollo 、 zk  、 etcd3
    type: nacos
    nacos:
      server-addr: 127.0.0.1:8848
      # 如果在nacos上添加了命名空间,则配置命令空间ID
      namespace:
      # 配置分组
      group: SEATA_GROUP
      username:
      password:
      context-path:
      ##if use MSE Nacos with auth, mutex with username/password attribute
      #access-key:
      #secret-key:
      data-id: seataServer.properties
  registry:
    # support: nacos 、 eureka 、 redis 、 zk  、 consul 、 etcd3 、 sofa
    type: nacos
    preferred-networks: 30.240.*
    nacos:
      application: seata-server
      server-addr: 127.0.0.1:8848
      group: SEATA_GROUP
      namespace:
      cluster: default
      username:
      password:
      context-path:
      ##if use MSE Nacos with auth, mutex with username/password attribute
      #access-key:
      #secret-key:
  server:
    service-port: 8091 #If not configured, the default is '${server.port} + 1000'
    max-commit-retry-timeout: -1
    max-rollback-retry-timeout: -1
    rollback-retry-timeout-unlock-enable: false
    enable-check-auth: true
    enable-parallel-request-handle: true
    retry-dead-threshold: 130000
    xaer-nota-retry-timeout: 60000
    enableParallelRequestHandle: true
    recovery:
      committing-retry-period: 1000
      async-committing-retry-period: 1000
      rollbacking-retry-period: 1000
      timeout-retry-period: 1000
    undo:
      log-save-days: 7
      log-delete-period: 86400000
    session:
      branch-async-queue-size: 5000 #branch async remove queue size
      enable-branch-async-remove: false #enable to asynchronous remove branchSession
  store:
    # support: file 、 db 、 redis
    mode: db
    session:
      mode: db
    lock:
      mode: db
    db:
      datasource: druid
      db-type: mysql
      driver-class-name: com.mysql.jdbc.Driver
      url: jdbc:mysql://127.0.0.1:3306/seata?rewriteBatchedStatements=true
      user: mysql
      password: mysql
      min-conn: 10
      max-conn: 100
      global-table: global_table
      branch-table: branch_table
      lock-table: lock_table
      distributed-lock-table: distributed_lock
      query-limit: 1000
      max-wait: 5000
  metrics:
    enabled: false
    registry-type: compact
    exporter-list: prometheus
    exporter-prometheus-port: 9898
  transport:
    rpc-tc-request-timeout: 15000
    enable-tc-server-batch-send-response: false
    shutdown:
      wait: 3
    thread-factory:
      boss-thread-prefix: NettyBoss
      worker-thread-prefix: NettyServerNIOWorker
      boss-thread-size: 1

設定ファイル config.txt を nacos にロードします

config.txt ファイルを変更する

config.txtファイルはseata/script/config-centerディレクトリ内にあり、変更する必要がある場所は次のとおりです。

  1. ストア.モード=db
  2. ストア.ロック.モード=db
  3. ストア.セッション.モード=db
  4. store.db データベースの構成は、上記の yml ファイルと同じように独自に変更されます。

ナコスにロードする

ファイルseata/script/config-center/nacosを実行するディレクトリを入力します。nacos-config.sh

sh nacos-config.sh -h 121.37.228.169 -p 8848 -g SEATA_GROUP -t 0af6e97b-a684-4647-b696-7c6d42aecce7 -u nacos -w nacos
  • -h: Nacos IP アドレス
  • -p: Nacos ポート番号
  • -g: グループグループ名
  • -t: ネームスペース ID (デフォルトでパブリックでない場合)
  • -u: ユーザー名
  • -w: パスワード
    実行が完了したら、Nacos 構成管理にログインして、ロードされたデータを表示します。
    ここに画像の説明を挿入

Seata サービスを開始する

通常起動

seata/binディレクトリに入り、次のコマンドを実行します。

sh seata-server.sh 

ここに画像の説明を挿入

ここで、起動時に異常事態に遭遇することがありますが、以下に起動時に遭遇した落とし穴をいくつか列挙します。に移動できます启动时遇到的坑

起動ログを表示する

私の Mac システムではログ ファイルを開くことができますが、他のシステムではシステムに応じてコマンドを実行するか、ファイルをseata/logs表示するにはディレクトリに直接入力する必要がありますstart.out

open /Users/ddz/Downloads/seata/logs/start.out

ここに画像の説明を挿入
起動が成功したことを示すログ出力アドレスが表示されます。

コンソールページを開く

コンソール ページでは、デフォルトのアカウント パスワードはseata/seataです。
ここに画像の説明を挿入

始動時にピットに遭遇

Seata を導入する際に私が遭遇したいくつかの落とし穴を以下に示します。参考までに、それらの間に違いがある可能性があります。

${console.user.username} の値を解決できません

例外情報: 値「${console.user.username}」のプレースホルダー「console.user.username」を解決できませんでした。
ここに画像の説明を挿入
解決策: 以前に別の名前に変更された yml ファイル内のすべての構成情報をconsole現在のファイルにコピーする必要があります。 application.yml1つ。ここでは、ログイン コンソール ページのアカウント パスワードを設定します。

${seata.security.secretKey} の値を解析できません

例外情報: 値 "${seata.security.secretKey}" のプレースホルダー 'seata.security.secretKey' を解決できませんでした
ここに画像の説明を挿入
解決策: 以前に別の名前に変更された yml ファイル内のすべての構成情報をseata.security現在の名前にコピーする必要がありますapplication.yml1つ。

データベース接続の問題

例外情報: com.mysql.jdbc.Exceptions.jdbc4.CommunicationsException: 通信リンク障害
MySQL5.7 より前のバージョンではセキュリティが低く、誰でもデータベースに接続できてしまうため、正式版 5.7 ではプライバシー保護が強化されています。また、データベースのランダムな変更を防ぐために、デフォルトの useSSL = true 値が採用されています。バージョン 8.0 では、SSL は依然として保持されており、デフォルト値は true です。
ここに画像の説明を挿入

解決策: データベース設定 URL の後に追加します&useSSL=false。yml 設定ファイルと Nacos の設定リストを確認する必要がありますstore.db.url
ここに画像の説明を挿入

Spring Boot プロジェクトに Seata を統合する

上記では、seata サーバーをローカルにインストールする方法と、Spring Boot プロジェクトへの Seata の統合を紹介しましたが、ここではデモを使用して紹介するだけであり、独自のビジネス ロジックに従って実装できます。

作業環境

  • MySQL 5.7.28
  • メイブン 3.5.4
  • JDK1.8
  • マイボット 3.4.1
  • 動的3.4.1

クラウド、ブート、アリババ環境

   <spring-boot.version>2.3.7.RELEASE</spring-boot.version>
   <spring-cloud.version>Hoxton.SR9</spring-cloud.version>
   <spring-cloud-alibaba.version>2.2.6.RELEASE</spring-cloud-alibaba.version>

依存関係を追加する

	<!--    MySQL    -->
	<dependency>
	    <groupId>mysql</groupId>
	    <artifactId>mysql-connector-java</artifactId>
	</dependency>
	<!--    Mybatis    -->
	<dependency>
	    <groupId>com.baomidou</groupId>
	    <artifactId>mybatis-plus-boot-starter</artifactId>
	    <version>3.4.1</version>
	</dependency>
	<!--    多数据源    -->
	<dependency>
	    <groupId>com.baomidou</groupId>
	    <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
	    <version>3.4.1</version>
	</dependency>
	<!--    Seata分布式事务    -->
	<dependency>
	    <groupId>com.alibaba.cloud</groupId>
	    <artifactId>spring-cloud-starter-alibaba-seata</artifactId>
	</dependency>

設定yml

server:
  port: 7001
spring:
  application:
    name: ddz-user
  cloud:
    nacos:
      discovery:
        # 服务分组
        group: ddz
        server-addr: 121.37.228.111:8848
        # 必须填命名空间的ID
#        namespace: 9ebef975-dcc0-4430-9c63-1c62d8a86d82
  datasource:
    dynamic:
      # 开启seata分布式事务
      seata: true
      strict: false
      primary: master
      datasource:
        master:
          url: jdbc:mysql://121.37.228.111:3306/ddz?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&rewriteBatchedStatements=true
          username: ddz
          password: ddz2023
        local:
          url: jdbc:mysql://127.0.0.1:3306/ddz?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&rewriteBatchedStatements=true
          username: root
          password: ddz2023

# MyBatis Plus配置
mybatis-plus:
  # 搜索指定包别名
  typeAliasesPackage: com.ddz.**.entity
  # 配置mapper的扫描,找到所有的mapper.xml映射文件
  mapperLocations: classpath*:mapper/**/*.xml
  global-config:
    db-config:
      id-type: auto
  configuration:
    # 开启驼峰,开启后,只要数据库字段和对象属性名字母相同,无论中间加多少下划线都可以识别
    map-underscore-to-camel-case: true

# Seata 配置
seata:
  application-id: seata-server
  # 是否启用数据源bean的自动代理
  enable-auto-data-source-proxy: false
  tx-service-group: default_tx_group  # 必须和服务器配置一样
  registry:
    type: nacos
    nacos:
      # Nacos 服务地址
      server-addr: 121.37.228.111:8848
      group: SEATA_GROUP
#      namespace: 9ebef975-dcc0-4430-9c63-1c62d8a86d82
      application: seata-server # 必须和服务器配置一样
      #      username:
      #      password:
      cluster: default
  config:
    type: nacos
    nacos:
      server-addr: 121.37.228.111:8848
      group: SEATA_GROUP
#      namespace: 9ebef975-dcc0-4430-9c63-1c62d8a86d82
  service:
    vgroup-mapping:
      default_tx_group: default # 必须和服务器配置一样
    disable-global-transaction: false
  client:
    rm:
      # 是否上报成功状态
      report-success-enable: true
      # 重试次数
      report-retry-count: 5

Seata をビジネス コードに統合する

mapper2 つのデータ ソースに基づいて2 つのクラスを作成し、controllerそれらをテストします。ここではテストの便宜上、ビジネス層を省略しています。

注釈を使用して@GlobalTransactionalグローバル トランザクションを管理する

ここに画像の説明を挿入

AT (自動補償) モードと TCC (2 フェーズ コミット) モードをデモします。

AT(自動補正)モードを使用する

AT モードでは、Seata は手動で補償ロジックを記述することなく、トランザクションを自動的に補償します。まず、ある口座から別の口座に資金を転送し、トランザクションの一貫性を確保する単純な転送シナリオを示します。

  1. @GlobalTransactional アノテーションを追加する
    @GlobalTransactional アノテーションを転送サービスのメソッドに追加して、グローバル トランザクションをマークします。
@Service
public class TransferService {
    
    
    
    @GlobalTransactional
    public void transfer(String fromAccount, String toAccount, double amount) {
    
    
        // 扣除转出账户金额
        deductAmount(fromAccount, amount);

        // 增加转入账户金额
        addAmount(toAccount, amount);
    }

    // 实现扣除金额逻辑
    // ...

    // 实现增加金额逻辑
    // ...
}
  1. AT モードのテスト AT モード
    でのトランザクション管理を検証するテスト ケースを作成します。
@RunWith(SpringRunner.class)
@SpringBootTest
public class TransferServiceTest {
    
    

    @Autowired
    private TransferService transferService;

    @Test
    public void testTransfer() {
    
    
        // 假设从账户 A 转账 100 到账户 B
        transferService.transfer("accountA", "accountB", 100.0);
    }
}

テスト ケースを実行して転送が成功したかどうかを確認し、ログをチェックして Seata がトランザクションを自動的に補正したかどうかを確認します。

TCC (2 フェーズ コミット) モードを使用する

TCC モードでは、トランザクションが正しく実行されることを保証するために、試行、確認、キャンセルの 3 つのフェーズのロジックを手動で記述する必要があります。注文、在庫の差し引き、注文の作成という 3 つの段階を含む、簡単な注文作成シナリオを示します。

  1. TCC インターフェイスの実装
    TCC インターフェイスを作成し、Try、confirm、Cancel の 3 つの段階のロジックを実装します。
public interface OrderTccService {
    
    

    @GlobalTransactional
    boolean createOrder(OrderDTO orderDTO);

    @TwoPhaseBusinessAction(name = "orderTccService", commitMethod = "confirmOrder", rollbackMethod = "cancelOrder")
    boolean tryCreateOrder(OrderDTO orderDTO);

    boolean confirmOrder(OrderDTO orderDTO);

    boolean cancelOrder(OrderDTO orderDTO);
}
  1. TCC ロジックの
    実装 実装クラスに TCC ロジックを記述します。
@Service
public class OrderTccServiceImpl implements OrderTccService {
    
    

    @Override
    public boolean tryCreateOrder(OrderDTO orderDTO) {
    
    
        // 预留库存逻辑
        // ...
        return true;
    }

    @Override
    public boolean confirmOrder(OrderDTO orderDTO) {
    
    
        // 确认创建订单逻辑
        // ...
        return true;
    }

    @Override
    public boolean cancelOrder(OrderDTO orderDTO) {
    
    
        // 取消创建订单逻辑
        // ...
        return true;
    }
}
  1. TCC モードをテストする
    TCC モードのトランザクション管理を検証するテスト ケースを作成します。
@RunWith(SpringRunner.class)
@SpringBootTest
public class OrderTccServiceTest {
    
    

    @Autowired
    private OrderTccService orderTccService;

    @Test
    public void testCreateOrder() {
    
    
        // 创建一个订单
        OrderDTO orderDTO = new OrderDTO();
        // 设置订单信息
        // ...

        orderTccService.createOrder(orderDTO);
    }
}

テスト ケースを実行して注文が正常に作成されたかどうかを確認し、ログをチェックして TCC モードの試行、確認、キャンセルの各フェーズが正しく実行されたかどうかを確認します。

セアタが踏んだピットを一体化

ここでは、統合プロセス中に私が遭遇したいくつかの落とし穴を示します。参考までに、それらの間に違いがある可能性があります。

テーブル「ddz.undo_log」が存在しません

例外情報: プロセス接続プロキシ コミット エラー: テーブル 'ddz.undo_log' が存在しません。
解決策: データ ソース内の Seata に必要なログ テーブルを切り取り、undo_log各データ ソースに新しいテーブルを追加します。

CREATE TABLE `undo_log` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `branch_id` bigint(20) NOT NULL,
  `xid` varchar(100) NOT NULL,
  `context` varchar(128) NOT NULL,
  `rollback_info` longblob NOT NULL,
  `log_status` int(11) NOT NULL,
  `log_created` datetime NOT NULL,
  `log_modified` datetime NOT NULL,
  `ext` varchar(100) DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

利用可能なサービス「null」が見つかりません。レジストリ設定が正しいことを確認してください。

例外情報: この理由は、config.txtnacos に Seata をロードしなかったためです。
解決策: コマンドを実行して、構成を Nacos 構成センターにロードします。上記を参照してください。把配置文件config.txt加载到nacos上

分散トランザクションが有効にならない

理由: 使用している複数のデータ ソースでは、デフォルトでは分散トランザクションdynamicが有効になっていませんSeata
解決策: yml 設定ファイルdynamicの下に設定を追加してseata: true、分散トランザクションを有効にします。

動的データソースがプライマリ データソースを見つけることができません

理由:これはデータソース構成情報のエラーです。この例外の理由は、データベース接続 (URL) の接続を間違って書いてしまったためです。
解決策:datasource次のデータ ソースの構成を再確認します。

通信リンク障害

理由: ここでの理由のほとんどは、MySQL が SSL 接続を行うかどうかを指定する必要があり、SSL 接続がデフォルトで有効になっているためです。
解決策: データベース接続構成 URL の後に追加するだけです&useSSL=false

要約する

分散システムが進化し続けるにつれて、分散トランザクションの分野も進化します。将来的には、さまざまなビジネス シナリオのニーズを満たすために、より分散されたトランザクション モデルとソリューションをさらに検討することができます。同時に、Seata は積極的なオープンソース プロジェクトとして、新しい機能と改善を導入し続ける予定であり、私たちは Seata コミュニティの更新に注意を払い、私たち自身の力を提供することができます。

さらに、 Seata に加えて、 、 、 などの他の分散トランザクション ソリューションもあります。TCC-TransactionこれらSAGAHSTCソリューションも、私たちが徹底的に調査し調査する価値があります。さまざまなビジネス シナリオに応じて、分散トランザクションの問題を解決するための最適なソリューションを選択できます。

参考文献

Nacos 公式ドキュメント
Seata 公式ドキュメント
Spring Boot 公式ドキュメント

おすすめ

転載: blog.csdn.net/weixin_45626288/article/details/132155575