分布式事务笔记

事务

c040cde86b5a269e4fcf55f6494d804e4df.jpg

 

6226d6c1a72641dd9323ecc28abe02ee2ec.jpg

 

 

实现分布式事务

dc78b1568c871a2107f3d9778b17f68a0ef.jpg

 

最好的方式就是 TCC 编程补偿式事务

 

两段式事务 2PC, 三段式事务 3PC

 

38d2c795c2cfd0759aa167629bfcde07967.jpg

 

三段式事务 就是 在 两段式事务 中间加多一段,进行 确认是否都可以提交事务了,减少 提交事务出现的 失败

两段事务,三段事务,实际 不会应用,是其他分布式事务解决办法的 实现基础和理论基础。

 

XA

00c35048b38fd5407e1149c033728db4673.jpg

实际基本不用,但是 MySQL 或者 orcal  就是 事务就是基于这个模型原理的。

1e61d7f2ebb45096535ddc668ed70aaf050.jpg

 

最终 强一致性: 要么都失败,要么都成功

会存在一些资源浪费,会有线程等待,处理速度慢,这样高并发之后容易出现服务宕机等问题。

比如  支付之前,先让支付服务等待,之后 让 订单处理服务完成事务提交之后,再去 处理支付,

这样就不会 产生 支付之后,订单 处理失败了,而支付金额比较难 撤销找回来。

 

TCC 柔性补偿式事务

2f0782e8bc114db9c772d26744f541a69e7.jpg

T尝试执行, C确认执行,  C取消操作

要么都去操作,提交事务,要么 全 取消 操作

62ee9eab0586dd610f9b26ae786f7303736.jpg

大部分场景使用 TCC 

 

分布式事务框架

4b37f3dd5167db328faae1c310a5861923e.jpg

 

4dafb90fbf8901e812cbfba626be9acb38f.jpg

 

 

TCC-Transaction

配置 tcc的数据源要独立,不能用来去处理 其他功能或者业务。 

TCC 运用要和业务相结合, 业务要有一个中间状态比如  支付中, 下单中 。  

出现事务异常则 调用 cancel 方法将 数据库状态 和数据 改为  比如 无效

没有事务异常,成功则 调用   confirmMethod  方法 去处理 处理成功,将状态改为 成功 

同时应用时候要保证 TCC处理中的 调用处理 幂等 

注意 当 使用 dubbo 整合TCC 的时候,要 将 服务接口api 类   配置在 tcc-transaction-dubbo.xml 里面,

而不是使用 dubbo 注解 (也就是将 dubbo服务和接口配置在xml里面,而不是使用 dubbo服务注解),否则会可能导致TCC 使用上 产生BUG 

比如下面这样

16c3faf15adc1b8765c3eaf7f5a5c2a800d.jpg

 

那么当 confirm 最后确认 执行的时候,出现了异常。那么TCC 是不会 将这个异常给抛出去的。也就是当 它是成功的。

TCC会记录该 异常 和事务信息到 数据库表,然后 定期去 重复执行该 confirm 方法, 直到它 提交成功了,也就是使用定时器去 修复事务。

如果一直修复不了,那么就需要人工介入了,自己去 改数据库啊,等等方式了。

86ec26479cf1535163471b20e6146998080.jpg

 

也就是 要 执行 分布式事务的时候,就会被 事务拦截器 拦截 处理,之后 交给 事务管理器,

同时将 事务信息存储在 事务存储器里面, 事务管理器会跟进 事务的变化状态,同时会将状态 更新到 事务存储器里面。

事务JOB  定时任务 会去 查看 事务存储器  里面 是否有 需要修复的事务 或者其他事情干。

事务JOB 和 事务管理器 并没有相互 调用执行, 他们面对的都是 事务存储器

 

拦截器

f26eab5f652f5a8212d0dc19693e9f917ca.jpg

CompensableTransactionInterceptor 就是 注解的 拦截器

ResourceXXX   就是资源拦截器

其实也就是 运用AOP 的  @Aspect , 将  @Compensable  注解的方法进行 拦截, 使用的是 

@Around("compensableService()")

在 方法执行之前 经过分布式事务的两个 拦截器,进行 处理, 然后 执行 方法处理业务,执行之后,

如果 成功执行没有问题就执行 confirm 方法,如果抛出了异常就执行 cancel 方法。

48cbcb97b3fd00a0f8f2f8090845be9e981.jpg

 

 

也就是 先 依次执行 分布式 服务接口的 方法体try , 没问题就 从 依次执行 微服务对应的 confirm 方法,如果try 异常, 就依次执行对应 各个接口方法的cancel 方法撤销补偿

67ebbb12f7b2ed741059d9c8dee147d45cf.jpg

 

TCC和业务结合比较紧密, TCC-Transaction 不能保证幂等性。

TCC分布式事务的核心是 资源: 分布式TCC表 数据不能和  业务库放在一起,避免出问题。

 

记录:

分布式事务:
	1、重点不是讲事务 -> 慕课网的其他课程【JDBC事务,Spring事务】
	2、事务如何做分布式


1、tcc-transaction-dubbo
	1.1 字节码代理 -> 创建接口的代理对象
	1.2 DubboTransactionContextEditor -> TRANSACTION_CONTEXT[标识事务状态]
				利用Dubbo的隐式参数来传递关键的非业务数据
				
				
2、tcc-transaction-spring
	封装了一些关键的Spring组件
	
3、问题:
	1、什么时候生成的TRANSACTION_CONTEXT隐式参数
	2、如何判断一个大的事务下,都有哪些小的事务
	3、为什么要有@Compensable注解
	4、两个拦截器都没有处理Confirm和Cancel

4、基础概念:
	主事务和分支事务【事务参与者】
	
5、事务拦截器作用:[Spring AOP的基本概念要熟练掌握]
	5.1 CompensableTransactionInterceptor
			5.1.1 将事务区分为Root事务和分支事务
			5.1.2 不断的修改数据库内事务数据的状态【初始化事务,修改事务状态】
			5.1.3 注册和清除事务管理器中队列内容
			5.1.4  继续做其他事
		
	5.2 ResourceCoordinatorInterceptor
			5.2.1 主要处理try阶段的事情
			5.2.2	在try阶段,就将所有的"资源"封装完成并交给事务管理器
			5.2.3 资源 -》 事务资源
							事务的参与者
									1、Confirm上下文
									2、Cancel上下文
									3、分支事务信息
			5.2.4 事务管理器修改数据库状态	
	5.3 调用目标对象 -> order red cap
	
6、小结:
	6.1 事务的相关信息【全局事务编号,乐观锁版本等要持久化存储】
	6.2 资源:*
				TCC 【try-confirm-cancel】
					try核心点: 预留业务资源
										  把事务数据资源存入库中
	6.3 流程:
			6.3.1 注册和初始化事务 -> 组织事务参与者 -> 执行目标try方法 -> 执行confirm和cancel方法

 

1、需要提供分布式事务支持的接口上添加@Compensable
2、在对应的接口实现上添加@Compensable
3、在接口实现上添加confirmMethod、cancelMethod、transactionContextEditor
4、实现对应的confirmMethod、cancelMethod
	注意: confirm方法和cancel方法必须与try方法在同一个类中

5、主事务的业务都已经实现的差不多的时候才调用子事务
	
	
	
	
注意:
	1、分布式事务里,不要轻易在业务层捕获所有异常	
	2、使用TCC-Transaction时,confirm和cancel的幂等性需要自己代码支持
	
思考: 
	为什么要在confirm、cancel里检查订单状态,而不直接修改为结束状态
	因为confirm确认的就是刚刚try方法里新增的一个订单。
	
	-》 为了保证服务的幂等性
	
幂等性:使用相同参数对同一资源重复调用某个接口的结果与调用一次的结果相同

 

对比

TCC事务的优缺点:

    优点:XA两阶段提交资源层面的,而TCC实际上把资源层面二阶段提交上提到了业务层面来实现。有效了的避免了XA两阶段提交占用资源锁时间过长导致的性能地下问题。

    缺点:主业务服务和从业务服务都需要进行改造,从业务方改造成本更高。还是航班预定案例,原来只需要提供一个购买接口,现在需要改造成try、confirm、canel3个接口,开发成本高。

 参考 https://my.oschina.net/dxqr/blog/2907143#h2_3

 

MQ 事务方案优点是:

  • 消息数据独立存储 ,降低业务系统与消息系统之间的耦合。
  • 吞吐量由于使用本地消息表方案。

缺点是:

  • 一次消息发送需要两次网络请求(half 消息 + commit/rollback 消息) 。
  • 业务处理服务需要实现消息状态回查接口。
  • 需要在业务系统中引入MQ,导致系统复杂度增加

参考 https://www.cnblogs.com/zjfjava/p/10425335.html

 

个人认为: 数据一致性实时要求不高,可以用MQ, 如果 调用链很长,比如 消费MQ消息的服务还需要发送 给其他服务MQ消息,

这样 TCC 就比较好,因为有框架,易用性会更好。 还有有资源的竞争,需要锁或者等待的话MQ也不合适。

事务处理比较简单,比如1-2 个服务之间处理分布式事务,那么使用 MQ会更好把控。毕竟TCC要建数据库事务表

 

 

转载于:https://my.oschina.net/ouminzy/blog/3083100

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值