TCC 防悬挂与幂等接入

TCC 防悬挂的目的是为了防止空回滚,即二阶段回滚方法比一阶段 try 方法先执行。TCC 幂等控制的目的是保证同一个分布式事务内,TCC 参与者的一阶段 try 方法会且只会被执行一次。

您可以根据以下步骤将 TCC 防悬挂与幂等配置在 TCC 参与者服务发布端的应用中:

  1. 创建表

  2. 配置 DAO

  3. 修改定义接口

  4. 修改实现接口

创建表

执行以下 DDL 语句,在业务数据库中创建表 dtx_tcc_action

CREATE TABLE `dtx_tcc_action`(
`action_id` varchar(96) NOT NULL COMMENT '分支事务号',
`action_name` varchar(64) DEFAULT NULL COMMENT '参与者名称',
`tx_id` varchar(128) NOT NULL COMMENT '主事务号',
`action_group` varchar(32) DEFAULT NULL COMMENT 'action group',
`status` varchar(10) DEFAULT NULL COMMENT '状态',
`param_data` varchar(4000) DEFAULT NULL COMMENT '一阶段方法参数数据',
`gmt_create` datetime NOT NULL COMMENT '创建时间',
`gmt_modified` datetime NOT NULL COMMENT '修改时间',
`sharding_key` varchar(128) DEFAULT NULL COMMENT '分库分表字段',
  PRIMARY KEY (`action_id`),
  UNIQUE KEY  `idx_tx_id`(`tx_id`,`action_name`)
);

配置 DAO

  • 如果用户使用的是 Ibastis,需要配置如下 bean:

    <bean class="com.alipay.sofa.dtx.tcc.dao.ibatis.IbatisTccAntiSuspendDAO">
         <property name="dataSource" ref="yourDataSourceBean"/>
    </bean>
  • 如果用户使用的是 Mybatis,配置如下 bean:

    <bean class="com.alipay.sofa.dtx.tcc.dao.mybatis.MybatisTccAntiSuspendDAO">
         <property name="dataSource" ref="yourDataSourceBean"/>
    </bean>
重要

其中的 dataSource 属性需配置成业务数据库的 DataSource bean。

修改定义接口

将 @TwoPhaseBusinessAction 注解的 antiSuspend 属性配置成 true,打开防悬挂功能:

public interface TccAction{
@TwoPhaseBusinessAction(name ="yourTccActionName", commitMethod ="confirm", rollbackMethod ="cancel", antiSuspend =true)
public boolean try(BusinessActionContext businessActionContext,@ShardingKeyint a,int b);
public boolean confirm(BusinessActionContext businessActionContext);
public boolean cancel(BusinessActionContext businessActionContext);
}
重要

如果业务数据库分库分表,则需要在一阶段方法的分库分表参数前添加 @ShardingKey 注解,单库单表无需添加。

修改实现接口

在 TCC 参与者一阶段 try 方法中,业务的数据库事务内,调用 TccTransactionController.doAntiSuspendControl() 方法添加防悬挂记录:

public class TccActionImpl implements TccAction {
    @Override
    public boolean try(
    BusinessActionContext businessActionContext, int a, int b)

    {

        transactionTemplate.execute(newTransactionCallback < Object > () {
        @Override
        public Object doInTransaction (TransactionStatus status){

            //手动防悬挂
            TccTransactionController.doAntiSuspendControl();

        }
    });

    }

    @Override
    public boolean confirm(BusinessActionContext businessActionContext) {

    }

    @Override
    public boolean cancel(BusinessActionContext businessActionContext) {

    }
}