分布式事务专题-TCC(4)

分布式事务专题-TCC(4)

1. 什么是TCC事务?

TCC是Try、Confirm、Cancel三个词语的缩写:

TCC要求每个分支事务实现三个操作:

  1. 预处理Try:Try操作做业务检查及资源预留
  2. 确认Confirm:Confirm做业务确认操作
  3. 撤销Cancel:Cancel实现一个与Try相反的操作即回滚操作
  • 正常情况
    在这里插入图片描述
  • 失败情况
    在这里插入图片描述

执行过程:

  1. TM首先发起所有的分支事务的try操作
  2. 若try操作全部成功,TM将会发起所有分支事务的Confirm操作。
  3. 如果任何一个分支事务的try操作执行失败,TM将会发起所有分支事务的Cancel操作.

    其中Confirm/Cancel操作若执行失败,TM会进行重试

2. TCC解决方案

目前市面上的TCC框架众多比如下面这几种:

框架名称Gitbub地址
tcc-transactionhttps://github.com/changmingxie/tcc-transaction
Hmilyhttps://github.com/yu199195/hmily
ByteTCChttps://github.com/liuyangming/ByteTCC
EasyTransactionhttps://github.com/QNJR-GROUP/EasyTransaction

上一节所讲的Seata也支持TCC,但Seata的TCC模式对Spring Cloud并没有提供支持

我们的目标是理解TCC的原 理以及事务协调运作的过程,因此更请倾向于轻量级易于理解的框架,因此最终确定了Hmily

Hmily是一个高性能分布式事务TCC开源框架。基于Java语言来开发(JDK1.8),支持Dubbo,Spring Cloud等RPC框架进行分布式事务。它目前支持以下特性.

  1. 支持嵌套事务(Nested transaction support).
  2. 采用disruptor框架进行事务日志的异步读写,与RPC框架的性能毫无差别。
  3. 支持SpringBoot-starter 项目启动,使用简单。
  4. RPC框架支持 : dubbo,motan,springcloud。
  5. 本地事务存储支持 : redis,mongodb,zookeeper,file,mysql。
  6. 事务日志序列化支持 :java,hessian,kryo,protostuff。
  7. 采用Aspect AOP 切面思想与Spring无缝集成,天然支持集群。
  8. RPC事务恢复,超时异常恢复等

Hmily利用AOP对参与分布式事务的本地方法与远程方法进行拦截处理,通过多方拦截,事务参与者能透明的调用到另一方的Try、Confirm、Cancel方法;传递事务上下文;并记录事务日志,酌情进行补偿,重试等。

Hmily不需要事务协调服务,但需要提供一个数据(mysql/mongodb/zookeeper/redis/file)来进行日志存
储。

TCC需要注意三种异常处理分别是空回滚、幂等、悬挂:

  • 空回滚:
    在没有调用 TCC 资源 Try 方法的情况下,调用了二阶段的 Cancel 方法,Cancel 方法需要识别出这是一个空回滚,然后直接返回成功。

解决思路是关键就是要识别出这个空回滚。思路很简单就是需要知道一阶段是否执行,如果执行了,那就是正常回
滚;如果没执行,那就是空回滚

  • 幂等
    通过前面介绍已经了解到,为了保证TCC二阶段提交重试机制不会引发数据不一致,要求 TCC 的二阶段 Try、Confirm 和 Cancel 接口保证幂等,这样不会重复使用或者释放资源。如果幂等控制没有做好,很有可能导致数据 不一致等严重问题

解决思路在上述“分支事务记录”中增加执行状态,每次执行前都查询该状态。

  • 悬挂
    悬挂就是对于一个分布式事务,其二阶段 Cancel 接口比 Try 接口先执行

解决思路是如果二阶段执行完成,那一阶段就不能再继续执行。在执行一阶段事务时判断在该全局事务下,“分支事务记录”表中是否已经有二阶段事务记录,如果有则不执行Try

3. Hmily实现分布式事务

  • maven依赖
<dependency>
	<groupId>org.dromara</groupId>
	<artifactId>hmily‐springcloud</artifactId>
	<version>2.0.4‐RELEASE</version>
</dependency>
  • 配置hmily,application.yml
dromara:
	hmily :
		serializer : kryo
		recoverDelayTime : 128
		retryMax : 30
		scheduledDelay : 128
		scheduledThreadMax : 10
		repositorySupport : db
		started: true
		hmilyDbConfig :
			driverClassName : com.mysql.jdbc.Driver
			url : jdbc:mysql://localhost:3306/bank?useUnicode=true
			username : root
			password : root

  • 新增配置类接收application.yml中的Hmily配置信息,并创建HmilyTransactionBootstrap Bean:
@Bean
public HmilyTransactionBootstrap hmilyTransactionBootstrap(HmilyInitService hmilyInitService){
	HmilyTransactionBootstrap hmilyTransactionBootstrap = new HmilyTransactionBootstrap(hmilyInitService);
	hmilyTransactionBootstrap.setSerializer(env.getProperty("org.dromara.hmily.serializer"));
	hmilyTransactionBootstrap.setRecoverDelayTime(Integer.parseInt(env.getProperty("org.dromara.hmily.recoverDelayTime")));
	hmilyTransactionBootstrap.setRetryMax(Integer.parseInt(env.getProperty("org.dromara.hmily.retryMax")));
	hmilyTransactionBootstrap.setScheduledDelay(Integer.parseInt(env.getProperty("org.dromara.hmily.scheduledDelay")));
	hmilyTransactionBootstrap.setScheduledThreadMax(Integer.parseInt(env.getProperty("org.dromara.hmily.scheduledThreadMax")));
	hmilyTransactionBootstrap.setRepositorySupport(env.getProperty("org.dromara.hmily.repositorySupport"));

	hmilyTransactionBootstrap.setStarted(Boolean.parseBoolean(env.getProperty("org.dromara.hmily.started")));
	HmilyDbConfig hmilyDbConfig = new HmilyDbConfig();
	hmilyDbConfig.setDriverClassName(env.getProperty("org.dromara.hmily.hmilyDbConfig.driverClassName"));
	hmilyDbConfig.setUrl(env.getProperty("org.dromara.hmily.hmilyDbConfig.url"));
	hmilyDbConfig.setUsername(env.getProperty("org.dromara.hmily.hmilyDbConfig.username"));
	hmilyDbConfig.setPassword(env.getProperty("org.dromara.hmily.hmilyDbConfig.password"));
	hmilyTransactionBootstrap.setHmilyDbConfig(hmilyDbConfig);
	return hmilyTransactionBootstrap;
}
  • 启动类增加@EnableAspectJAutoProxy并增加org.dromara.hmily的扫描项:
@SpringBootApplication
@EnableDiscoveryClient
@EnableHystrix
@EnableFeignClients(basePackages = {"cn.itcast.dtx.tccdemo.bank1.spring"})
@ComponentScan({"cn.itcast.dtx.tccdemo.bank1","org.dromara.hmily"})
public class Bank1HmilyServer {
	public static void main(String[] args) {
		SpringApplication.run(Bank1HmilyServer.class, args);
	}
}

4. 小结

如果拿TCC事务的处理流程与2PC两阶段提交做比较,2PC通常都是在跨库的DB层面,而TCC则在应用层面的处理,需要通过业务逻辑来实现。这种分布式事务的实现方式的优势在于,可以让应用自己定义数据操作的粒度,使得降低锁冲突、提高吞吐量成为可能.

而不足之处则在于对应用的侵入性非常强,业务逻辑的每个分支都需要实现try、confirm、cancel三个操作。此外,其实现难度也比较大,需要按照网络状态、系统故障等不同的失败原因实现不同的回滚策略。

5. 链接

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值