TCC分布式事务之一 —— tcc-transaction-1.2.x最新版整合spring cloud + dubbo + zookeeper

tcc-transaction作为github开源tcc分布式事务框架,对比其他tcc开源框架,星数排名第一,可以异步处理,也可以同步处理。

Github使用指南1.2.x:https://github.com/changmingxie/tcc-transaction/wiki/%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%971.2.x

tcc三个阶段

Try: 尝试执行业务

完成所有业务检查(一致性)
预留必须业务资源(准隔离性)

Confirm: 确认执行业务

真正执行业务
不作任何业务检查
只使用Try阶段预留的业务资源
Confirm操作满足幂等性

Cancel: 取消执行业务

释放Try阶段预留的业务资源
Cancel操作满足幂等性

maven配置

			<!--tcc-transaction核心包-->
			<dependency>
				<groupId>org.mengyun</groupId>
				<artifactId>tcc-transaction-spring</artifactId>
				<version>1.2.12</version>
			</dependency>
			<!--tcc-transaction整合dubbo核心包-->
			<dependency>
				<groupId>org.mengyun</groupId>
				<artifactId>tcc-transaction-dubbo</artifactId>
				<version>1.2.12</version>
			<exclusions>
				<exclusion>
					<groupId>org.apache.dubbo</groupId>
					<artifactId>dubbo</artifactId>
				</exclusion>
				<exclusion>
					<artifactId>zookeeper</artifactId>
					<groupId>org.apache.zookeeper</groupId>
				</exclusion>
				<exclusion>
					<artifactId>curator-recipes</artifactId>
					<groupId>org.apache.curator</groupId>
				</exclusion>
			</exclusions>
			<dependency>
				<groupId>org.springframework.cloud</groupId>
				<artifactId>spring-cloud-starter-zookeeper-discovery</artifactId>
				<version>2.2.1.RELEASE</version>
			</dependency>
			<dependency>
	            <groupId>com.alibaba.cloud</groupId>
	            <artifactId>spring-cloud-starter-dubbo</artifactId>
	            <version>2.2.1.RELEASE</version>
	            <exclusions>
	                <exclusion>
	                    <groupId>org.apache.dubbo</groupId>
	                    <artifactId>dubbo</artifactId>
	                </exclusion>
	            </exclusions>
	        </dependency>
	        <dependency>
	            <groupId>org.apache.dubbo</groupId>
	            <artifactId>dubbo</artifactId>
	            <version>2.7.7</version>
	        </dependency>
		</dependency>

首先需要配置tcc服务远程tcc服务的config

tcc服务配置

@Configuration
public class TccConfig {
    
    

    @Bean
    public DefaultRecoverConfig defaultRecoverConfig(){
    
    
        DefaultRecoverConfig defaultRecoverConfig = new DefaultRecoverConfig();
        defaultRecoverConfig.setMaxRetryCount(30);   //最大重试次数
        defaultRecoverConfig.setRecoverDuration(30); //恢复持续时间
        defaultRecoverConfig.setCronExpression("0/30 * * * * ?"); //每30秒检查一次是否需要恢复(检查对应的日志表有无需要恢复的数据)//每30秒检查一次是否需要恢复
        defaultRecoverConfig.setDelayCancelExceptions(Sets.newHashSet(org.apache.dubbo.remoting.TimeoutException.class));
        return defaultRecoverConfig;
    }

    @Bean("transactionRepository")
    public SpringJdbcTransactionRepository springJdbcTransactionRepository(){
    
    
        SpringJdbcTransactionRepository springJdbcTransactionRepository = new SpringJdbcTransactionRepository();

        springJdbcTransactionRepository.setDomain("CONSUMER");    //domain
        springJdbcTransactionRepository.setTbSuffix("_CONSUMER"); //配置tcc日志表名称后缀:这里为:tcc_transaction_consumer

        //tcc所需分布式事务日志数据源(也可以使用其他数据源框架)
        HikariDataSource hikariDataSource = new HikariDataSource();
        hikariDataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
        hikariDataSource.setJdbcUrl("jdbc:mysql://127.0.0.1:3306/tcc?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=CTT");
        hikariDataSource.setUsername("root");
        hikariDataSource.setPassword("root");
        springJdbcTransactionRepository.setDataSource(hikariDataSource);

        return springJdbcTransactionRepository;
    }

}

远程tcc服务配置,只需要修改以下两处代码,其他配置都相同

		springJdbcTransactionRepository.setDomain("PROVIDER");
        springJdbcTransactionRepository.setTbSuffix("_PROVIDER"); //配置tcc日志表名称后缀:这里为:tcc_transaction_provider
  1. service定义tcc服务三个阶段
    asyncConfirm = false:是否异步处理confirm阶段,默认false,也就是同步处理
    asyncCancel = false:是否异步处理cancel阶段,默认false,也就是同步处理
@Service
public class TccService{
    
    
	
	@DubboReference(check = false, retries = 0, timeout = 30000) //dubbo rpc远程过程调用
	private TestService testService;
	
 	@Override
    @Transactional
    @Compensable(confirmMethod = "commit", cancelMethod = "rollback", asyncConfirm = false, asyncCancel = false, delayCancelExceptions = {
    
    SocketTimeoutException.class, org.apache.dubbo.remoting.TimeoutException.class})
    public void doTry(@UniqueIdentity TransactionContext transactionContext, String accountNo, String to, BigDecimal amount) {
    
    
    	//try阶段
    	testService.remoteDoTry(transactionContext, accountNo, amount);
	}
	//如果try阶段成功,commit阶段必须成功,如果commit阶段抛出异常,则会重试commit阶段
 	@Transactional
    public void commit(TransactionContext transactionContext, String accountNo, String to, BigDecimal amount) {
    
    
    	//commit阶段
	}
 	@Transactional
    public void rollback(TransactionContext transactionContext, String accountNo, String to, BigDecimal amount) {
    
    
    	//rollback阶段
	}

controller调用:

@RestController
public class TestController {
    
    

	@Autowired
	private TccService tccService;
	
    @GetMapping("tcc")
    @ResponseBody
    public String tcc(String from, String to, BigDecimal amount) throws Exception {
    
    
        try{
    
    
            tccService.doTry(null, from, to, amount);
            return "success";
        } catch (Exception e){
    
    
            return "fail:" + e.getMessage();
        } finally {
    
    
            System.out.println("success finally");
        }
    }
}
  1. service定义远程tcc服务三个阶段
 	@Override
    @Transactional
    @Compensable(confirmMethod = "remoteCommit", cancelMethod = "remoteRollback", asyncConfirm = false, asyncCancel = false, delayCancelExceptions = {
    
    SocketTimeoutException.class, org.apache.dubbo.remoting.TimeoutException.class})
    public void remoteDoTry(@UniqueIdentity TransactionContext transactionContext, String accountNo, BigDecimal amount) {
    
    
    	//try阶段
	}
	//如果try阶段成功,commit阶段必须成功,如果commit阶段抛出异常,则会重试commit阶段
 	@Transactional
    public void remoteCommit(TransactionContext transactionContext, String accountNo, BigDecimal amount) {
    
    
    	//commit阶段
	}
 	@Transactional
    public void remoteRollback(TransactionContext transactionContext, String accountNo, BigDecimal amount) {
    
    
    	//rollback阶段
	}

TestService接口,注意远程接口上加上@Compensable注解

	@Compensable
    void remoteDoTry(TransactionContext transactionContext, String accountNo, BigDecimal amount);

核心代码已经完成,配置启动类

@SpringBootApplication
@EnableDiscoveryClient
@EnableDubbo 			 //启动dubbo配置与注解
@EnableAspectJAutoProxy  //启动切面类
@ImportResource(locations = {
    
    "classpath:tcc-transaction.xml", "classpath:tcc-transaction-dubbo.xml"}) //加载框架tcc-transaction配置
public class Application {
    
    

    public static void main(String[] args) {
    
    
        SpringApplication.run(Application .class, args);
    }

}

tcc数据库配置

配置tcc数据库,因为前面配置的数据库名称为tcc,并且tcc服务配置的表后缀为_CONSUMER远程tcc服务配置的表后缀为_PROVIDER,所以在tcc数据库创建两张表,下面是sql脚本
在这里插入图片描述
sql脚本,字段都是相同的,不同的只是表名称后缀

CREATE TABLE `tcc_transaction_consumer` (
  `TRANSACTION_ID` int(11) NOT NULL AUTO_INCREMENT,
  `DOMAIN` varchar(100) DEFAULT NULL,
  `GLOBAL_TX_ID` varbinary(32) NOT NULL,
  `BRANCH_QUALIFIER` varbinary(32) NOT NULL,
  `CONTENT` varbinary(8000) DEFAULT NULL,
  `STATUS` int(11) DEFAULT NULL,
  `TRANSACTION_TYPE` int(11) DEFAULT NULL,
  `RETRIED_COUNT` int(11) DEFAULT NULL,
  `CREATE_TIME` datetime DEFAULT NULL,
  `LAST_UPDATE_TIME` datetime DEFAULT NULL,
  `VERSION` int(11) DEFAULT NULL,
  `IS_DELETE` tinyint(1) NOT NULL DEFAULT '0',
  PRIMARY KEY (`TRANSACTION_ID`),
  UNIQUE KEY `UX_TX_BQ` (`GLOBAL_TX_ID`,`BRANCH_QUALIFIER`)
) ENGINE=InnoDB AUTO_INCREMENT=378 DEFAULT CHARSET=utf8;

CREATE TABLE `tcc_transaction_provider` (
  `TRANSACTION_ID` int(11) NOT NULL AUTO_INCREMENT,
  `DOMAIN` varchar(100) DEFAULT NULL,
  `GLOBAL_TX_ID` varbinary(32) NOT NULL,
  `BRANCH_QUALIFIER` varbinary(32) NOT NULL,
  `CONTENT` varbinary(8000) DEFAULT NULL,
  `STATUS` int(11) DEFAULT NULL,
  `TRANSACTION_TYPE` int(11) DEFAULT NULL,
  `RETRIED_COUNT` int(11) DEFAULT NULL,
  `CREATE_TIME` datetime DEFAULT NULL,
  `LAST_UPDATE_TIME` datetime DEFAULT NULL,
  `VERSION` int(11) DEFAULT NULL,
  `IS_DELETE` tinyint(1) NOT NULL DEFAULT '0',
  PRIMARY KEY (`TRANSACTION_ID`),
  UNIQUE KEY `UX_TX_BQ` (`GLOBAL_TX_ID`,`BRANCH_QUALIFIER`)
) ENGINE=InnoDB AUTO_INCREMENT=378 DEFAULT CHARSET=utf8;

最后附一张使用apache jmeter压力测试工具的图:测试为100个线程,每个线程吞吐量为10,测试数据是否准确:
在这里插入图片描述
在这里插入图片描述
调用处理次数1000次没有问题,数据库数据也没有问题 !

至此,tcc分布式事务就完成了,如果还有问题的小伙伴可以留言,看到会第一时间回答,有帮助的朋友点个赞-点个赞-点个赞,笔芯~

猜你喜欢

转载自blog.csdn.net/a251628111/article/details/107203846