sptingboot は Seata1.6.1 (TCC モード) を統合します

前回の記事からの続き:sptingbootがseata1.6.1を統合(ATモード)

はじめに公式紹介

TCCモード、基礎となるデータ リソースに依存しないトランザクション サポート:
1 フェーズprepare 動作:カスタムprepareロジックの呼び出し。
フェーズ 2 のcommit動作:カスタムロジックを呼び出しますcommit
フェーズ 2 のrollback動作:カスタムロジックを呼び出しますrollback
いわゆる TCC モードは、カスタマイズされたブランチ トランザクションのグローバル トランザクション管理への統合のサポートを指します。

分散グローバル トランザクションは 2 フェーズ コミット モデルです。グローバル トランザクションは複数のブランチ トランザクションで構成されます。ブランチ トランザクションは 2 段階コミット モデルの要件を満たす必要があります。つまり、各ブランチ トランザクションは独自のトランザクションを持つ必要があります。

  • ステージ 1 のprepare動作
  • ステージ 2commitまたはrollback 行動
    ここに画像の説明を挿入します

プロセス

  1. 前の記事 プロジェクトのコピーと命名lagou_parent_seata_tcc
  • 親プロジェクトの依存関係、.iml ファイル、および .pom ファイルを変更する
    ここに画像の説明を挿入します
  1. 各 (business\order\point\storage) サブプロジェクトのスタートアップ クラスを変更します。
//修改前
@SpringBootApplication(scanBasePackages = "com.lagou",exclude = DataSourceAutoConfiguration.class)
//修改后
@SpringBootApplication
  1. …_common_db サブプロジェクト
  • データ ソース プロキシ構成クラスをコメント化するか削除しますDataSourceConfiguration(AT には必須、TCC には不要)
  • 設定ファイル
# staet----------------------------seata服务配置
seata:
  # 切换XA模式
#  enable: true
#  data-source-proxy-mode: TCC
#  enable-auto-data-source-proxy: false
  config:
    type: nacos
    nacos:
      server-addr: 127.0.0.1:8848
      namespace: seata-server
      group: SEATA_GROUP
      username: nacos
      password: nacos
  registry:
    type: nacos
    nacos:
      server-addr: 127.0.0.1:8848
      namespace: seata-server
      application: seata-server
      group: SEATA_GROUP
      username: nacos
      password: nacos
  service:
    vgroup-mapping:
      default_tx_group: default
    disable-global-transaction: false
    grouplist:
      default: 127.0.0.1:8091
  tx-service-group: default_tx_group
spring:
  cloud:
    alibaba:
      seata:
        tx-service-group: default_tx_group
logging:
  level:
    seata: debug

  1. 注文プロジェクトを例として、準備、コミット、ロールバックのロジックをカスタマイズします。
  • \point\storage プロジェクトは同じです
  • OrderService.java
@LocalTCC
public interface OrderService extends IService<Order> {
    
    
    @TwoPhaseBusinessAction(name = "addTcc", commitMethod = "addCommit", rollbackMethod = "addRollback")
    public void addOrder(@BusinessActionContextParameter(paramName = "order") Order order);

    public boolean addCommit(BusinessActionContext context);

    public boolean addRollback(BusinessActionContext context);
}
package com.lagou.order.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lagou.order.entity.Order;
import com.lagou.order.mapper.OrderMapper;
import com.lagou.order.service.OrderService;
import io.seata.rm.tcc.api.BusinessActionContext;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
@Slf4j
@Service
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements OrderService {
    
    

    @Override
    @Transactional
    public void addOrder(Order order) {
    
    
        try {
    
    
            order.setCreateTime(new Date());//设置订单创建时间
            order.setStatus(0); //try 预检查阶段
            this.save(order);//保存订单
        } catch (Exception e) {
    
    
            e.printStackTrace();
        }
    }

    /**
     * add
     * @param context
     * @return
     */
    @Override
    public boolean addCommit(BusinessActionContext context) {
    
    
        Order contextOrder = JSON.parseObject(context.getActionContext("order").toString(), Order.class);
        if (null != contextOrder) {
    
    
            contextOrder=this.getById(contextOrder.getId());

            if(null != contextOrder){
    
    
                contextOrder.setStatus(1);
                this.saveOrUpdate(contextOrder);
            }
        }
        log.info("OrderService.addCommit---------->xid:{},提交成功",context.getXid());
        return true;
    }

    @Override
    public boolean addRollback(BusinessActionContext context) {
    
    
        Order contextOrder = JSON.parseObject(context.getActionContext("order").toString(), Order.class);
        if (null != contextOrder) {
    
    
            contextOrder=this.getById(contextOrder.getId());

            if(null != contextOrder){
    
    
                this.removeById(contextOrder.getId());
            }
        }
        log.info("OrderService.addRollback---------->xid:{},回滚成功",context.getXid());
        return true;
    }


}

  • アノテーションTCC では、 TCC モードでのビジネス処理の方法を示すため
    に追加する必要もあります。ここで、パラメーターはグローバル トランザクション アノテーションの名前を示し、送信とロールバックの通知方法をそれぞれ示します。注釈。注釈付きパラメータは actionContext に直接配置できます。@GlobalTransactional
    @LocalTCC
    @TwoPhaseBusinessActionnamecommitMethodrollbackMethod
    @BusinessActionContextParameter
  1. サービス開始
  • ナコス
    ここに画像の説明を挿入します

  • シータサーバー
    ここに画像の説明を挿入します

  • アイデアプロジェクト
    ここに画像の説明を挿入します

確認する

在庫は 100 です。注文が 100 を超えると、分散トランザクションのロールバックがトリガーされます。
http://localhost:8000/test1 通常通りに注文してポイントを加算し、在庫を減らします。
http://localhost:8000/test2 異常な発注、在庫不足、注文とポイントのロールバック。

  • 症例リンク
  • http://localhost:8000/test1通常通りに注文し、ポイントを追加し、在庫を減らします。
    ここに画像の説明を挿入します
  • http://localhost:8000/test2異常な注文、在庫不足、注文とポイントのロールバック。
    ここに画像の説明を挿入します

質問

問題を確認したところ、seata バージョン 1.5.1 以降ではTCC冪等制御、ハング防止、空のロールバックがサポートされていることがわかりました。準備フェーズがインターフェイスに追加されuseTCCFence = true、分散トランザクションのデータベースにテーブルを追加するために使用されますtcc_fence_logでも罠にはまってしまいました…奪えば出useTCCFence = trueてきません。NullPointerException
ここに画像の説明を挿入します

@LocalTCC
public interface OrderService extends IService<Order> {
    
    
    @TwoPhaseBusinessAction(name = "addTcc", commitMethod = "addCommit", rollbackMethod = "addRollback",useTCCFence = true)
    public void addOrder(@BusinessActionContextParameter(paramName = "order") Order order);

    public boolean addCommit(BusinessActionContext context);

    public boolean addRollback(BusinessActionContext context);
}
  • テーブル構造
CREATE TABLE `tcc_fence_log` (
  `xid` varchar(128) NOT NULL COMMENT 'global id',
  `branch_id` bigint(20) NOT NULL COMMENT 'branch id',
  `action_name` varchar(64) NOT NULL COMMENT 'action name',
  `status` tinyint(4) NOT NULL COMMENT 'status(tried:1;committed:2;rollbacked:3;suspended:4)',
  `gmt_create` datetime(3) NOT NULL COMMENT 'create time',
  `gmt_modified` datetime(3) NOT NULL COMMENT 'update time',
  PRIMARY KEY (`xid`,`branch_id`),
  KEY `idx_gmt_modified` (`gmt_modified`),
  KEY `idx_status` (`status`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
  • 問題 (この場合も問題は残ります)
java.lang.NullPointerException: null
	at io.seata.rm.tcc.TCCFenceHandler.commitFence(TCCFenceHandler.java:146) ~[seata-all-1.6.1.jar:1.6.1]
	at io.seata.rm.tcc.TCCResourceManager.branchCommit(TCCResourceManager.java:106) ~[seata-all-1.6.1.jar:1.6.1]
	at io.seata.rm.AbstractRMHandler.doBranchCommit(AbstractRMHandler.java:98) ~[seata-all-1.6.1.jar:1.6.1]
	at io.seata.rm.AbstractRMHandler$1.execute(AbstractRMHandler.java:54) ~[seata-all-1.6.1.jar:1.6.1]
	at io.seata.rm.AbstractRMHandler$1.execute(AbstractRMHandler.java:50) ~[seata-all-1.6.1.jar:1.6.1]
	at io.seata.core.exception.AbstractExceptionHandler.exceptionHandleTemplate(AbstractExceptionHandler.java:131) ~[seata-all-1.6.1.jar:1.6.1]
	at io.seata.rm.AbstractRMHandler.handle(AbstractRMHandler.java:50) ~[seata-all-1.6.1.jar:1.6.1]
	at io.seata.rm.DefaultRMHandler.handle(DefaultRMHandler.java:61) ~[seata-all-1.6.1.jar:1.6.1]
	at io.seata.core.protocol.transaction.BranchCommitRequest.handle(BranchCommitRequest.java:35) ~[seata-all-1.6.1.jar:1.6.1]
	at io.seata.rm.AbstractRMHandler.onRequest(AbstractRMHandler.java:150) ~[seata-all-1.6.1.jar:1.6.1]
	at io.seata.core.rpc.processor.client.RmBranchCommitProcessor.handleBranchCommit(RmBranchCommitProcessor.java:63) ~[seata-all-1.6.1.jar:1.6.1]
	at io.seata.core.rpc.processor.client.RmBranchCommitProcessor.process(RmBranchCommitProcessor.java:58) ~[seata-all-1.6.1.jar:1.6.1]
	at io.seata.core.rpc.netty.AbstractNettyRemoting.lambda$processMessage$2(AbstractNettyRemoting.java:281) ~[seata-all-1.6.1.jar:1.6.1]
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) ~[na:na]
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) ~[na:na]
	at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) ~[netty-all-4.1.53.Final.jar:4.1.53.Final]
	at java.base/java.lang.Thread.run(Thread.java:834) ~[na:na]

おすすめ

転載: blog.csdn.net/u014535922/article/details/131134208