"Microservice Combat" Chapter 30 Distributed Transaction Framework Seata TCC Mode

Series Article Directory

Chapter 30 Distributed transaction framework seata TCC mode
Chapter 29 Distributed transaction framework seata AT mode

insert image description here



foreword

This chapter introduces the distributed transaction framework seata TCC mode, and the previous chapter introduces seata and its integration into Springboot and microservice frameworks.

1. TCC mode

A distributed global transaction, the whole is a two-phase commit model. A global transaction is composed of several branch transactions. The branch transactions must meet the requirements of the two-phase commit model, that is, each branch transaction needs to have its own:

  • One-stage prepare behavior
  • Two-phase commit or rollback behavior
    insert image description here

According to the different behavior modes of the two phases, we divide branch transactions into Automatic (Branch) Transaction Mode and TCC (Branch) Transaction Mode.

1.1. AT mode (reference link TBD) is based on a relational database that supports local ACID transactions

1.1.1, one-stage prepare behavior

In the local transaction, the business data update and the corresponding rollback log records are submitted together.

1.1.2, two-stage commit behavior

It will end successfully immediately, and the rollback logs will be automatically and asynchronously cleaned up in batches.

1.1.3, two-stage rollback behavior

By rolling back logs, compensation operations are automatically generated to complete data rollback.

1.2, TCC mode, does not depend on the transaction support of the underlying data resources

1.2.1, one-stage prepare behavior

Call custom prepare logic. try

1.2.2. Two-stage commit behavior

Call custom commit logic. confirm

1.2.3, two-stage rollback behavior

Call custom rollback logic. cancel

2. Examples

2.1, define the controller

/**
 * 采购
 */
@PostMapping("/purchaseTCC")
@GlobalTransactional
public String purchaseTCC(@RequestBody OrderDTO orderDTO){
    
    
    this.businessTCCService.purchase(orderDTO);
    return "success";
}

2.2. Define service

@LocalTCC
public interface BusinessTCCService {
    
    
    /**
     * 采购 执行资源检查及预留操作
     */
    @TwoPhaseBusinessAction(name = "purchase",commitMethod = "commit",rollbackMethod = "rollback")
    public void purchase(@BusinessActionContextParameter(paramName = "orderDTO") OrderDTO orderDTO);

    /**
     * 全局事务进行提交
     * @param businessActionContext
     * @return
     */
    boolean commit(BusinessActionContext businessActionContext);

    /**
     * 全局事务进行不回滚
     * @param businessActionContext
     * @return
     */
    boolean rollback(BusinessActionContext businessActionContext);
}

package com.xxxx.store.business.service.impl;

import cn.hutool.crypto.SecureUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.xxxx.store.business.service.BusinessService;
import com.xxxx.store.business.service.BusinessTCCService;
import com.xxxx.store.business.service.OrderService;
import com.xxxx.store.business.service.StorageService;
import com.xxxx.store.common.dto.OrderDTO;
import com.xxxx.store.common.dto.StorageDTO;
import io.seata.rm.tcc.api.BusinessActionContext;
import io.seata.spring.annotation.GlobalTransactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.File;

@Service
public class BusinessTCCServiceImpl implements BusinessTCCService {
    
    
    @Value("${file.path}")
    private String filePath;
    @Autowired
    private OrderService orderService;
    @Autowired
    private StorageService storageService;

    @Override
    public void purchase(OrderDTO orderDTO) {
    
    
        //减库存
        this.storageService.deduct(new StorageDTO(null,orderDTO.getCommodityCode(),orderDTO.getCount()));
        //创建订单
        this.orderService.create(orderDTO);
    }

    @Override
    public boolean commit(BusinessActionContext businessActionContext) {
    
    
        System.out.println("事务ID:" + businessActionContext.getXid());
        return true;
    }

    @Override
    public boolean rollback(BusinessActionContext businessActionContext) {
    
    
        JSONObject jSONObject = (JSONObject)businessActionContext.getActionContext("orderDTO");

        OrderDTO orderDTO = jSONObject.toJavaObject(OrderDTO.class);
        StorageDTO storageDTO = new StorageDTO(null, orderDTO.getCommodityCode(), orderDTO.getCount());

        String s = JSON.toJSONString(storageDTO);
        String md5 = SecureUtil.md5(s);
        System.out.println("**************触发回滚操作:" + filePath + md5);
        File file = new File(filePath + md5);
        file.delete();
        return true;
    }

    /*@Override
    public void purchase(OrderDTO orderDTO) {
        //减库存
        this.storageService.deduct(new StorageDTO(null,orderDTO.getCommodityCode(),orderDTO.getCount()));
        //创建订单
        this.orderService.create(orderDTO);
    }*/

}
annotation describe
@LocalTCC It must be annotated on the interface, otherwise it will not take effect. This interface can be an ordinary business interface, as long as the corresponding method of TCC's two-phase submission is implemented, it is applicable to TCC in SpringCloud+Feign mode.
@TwoPhaseBusinessAction Annotate the try method, where name is the bean name of the current tcc method, just write the method name (globally unique), commitMethod points to the commit method, and rollbackMethod points to the transaction rollback method. After specifying the three methods, seata will automatically call the commit method or rollback method according to the success or failure of the global transaction.
@BusinessActionContextParameter Use this annotation to pass parameters to the two-phase commit or rollback method for easy calling.
BusinessActionContext For the TCC transaction context, use BusinessActionContext.getActionContext("params") to get the parameters defined in the first-stage try, and refer to this parameter in the second stage to perform business rollback operations.

Suggestion: You can use @Transational in the try method to directly control the transaction of the relational database through spring, and perform rollback operations. The rollback operation of middleware such as non-relational databases can be handled by the rollbackMethod method.

Suggestion: The try interface cannot catch exceptions, otherwise TCC will recognize the operation as successful and directly execute the two-stage commit method.

Guess you like

Origin blog.csdn.net/s445320/article/details/131150756