分布式事务业界主流方案
2019-11-05

一句话总结:分布式事务业界主流方案:两阶段提交方案(包括XA方案和TCC方案)、消息队列方案。

 

1、两阶段提交方案

1.1 XA方案

XA协议流程可以查看作者另一篇“2PC两阶段提交协议”,XA方案是资源层的两阶段提交,通常应用于多数据库操作的场景,如Mysql 5.5版本以上Innodb引擎原生支持XA。应用层可搭配Spring JTA对接数据库XA,开发人员即可无需处理多库事务,交给框架和DB处理。

1.2 TCC方案

TCC方案是应用层的两阶段提交,通常应用于完全独立的多个系统间通过RPC调用,需要提供逆操作接口用于回滚。甚至作者认为TCC比两阶段提交还简单,可以将try和confirm合并成一阶段提交,TCC在try操作完后默认认为commit都会成功。

1.3 两阶段提交方案优化

我们知道两阶段提交协议的问题在于,协调者在第二阶段发出commit/rollback后就不管了,这里可以优化:

1)超时重试,接口幂等性(基于事务ID)。优化网络短暂中断场景,单次commit/rollback消息丢失,重试进行解决

2)引入对账机制,定时对账,异常时触发对账

3)腾讯云金融级TDSQL XA方案设计思路,对于参与者,若未收到commit/rollback消息或收到执行异常,需有一套机制保证参与者无论如何都能成功执行事务。

这套机制需要两个条件:

1、协调者在发出commit/rollback命令之前记录事务ID和事务状态

2、参与者上有个独立守护进程,此进程不会挂掉(挂掉就重启),定时检查参与者有prepare状态数据并超过一定时间后,此进程就去协调者上守护进程查询事务状态(不断查询,网络中断退出集群),查询到状态后在本节点上执行事务,通常prepare成功commit/rollback会成功,若不成功该进程也要去解除不成功的因素如解除死锁让其成功

TCC方案优化思路网上也有人整理,参考下图:

4)第3点优化方案较复杂,通常两阶段提交方案在多次重试无效后,就告警由人工介入

 

2、消息队列方案

消息队列方案主要是解决两阶段提交阻塞式,性能不高的问题。它的思路是分段执行,各个参与者先各自执行,再由异步消息来确保最终一致性。整个过程没有同步阻塞,提高了并发和性能。思路有点类似乐观锁,先假定各个参与者都能成功执行。

消息队列方案为了保证最终一致性,事务状态的凭据很重要,实在不行最后人工介入查看凭据,需要业务独立创建一张表存储,类似状态机机制,每个节点写业务表和写事务状态表在同一个事务中,确保事务状态写成功。

正常流程发起方发出消息,其他参与者收到消息执行本地事务,执行成功向发起方返回执行成功消息,发起方收到消息在事务表中标识该参与者事务完成或删除此事务信息。参与者执行失败则发起回滚消息,此时其变为消息发起方,流程与前面一样。

每个节点上起定时线程,检查未处理完成或发出失败的消息,重新发出消息,即重试机制和幂等性机制。

 

目前阿里云的RocketMQ提供了无需业务耦合即可事务的消息队列,主要优化了事务状态存储和查询、类两阶段的消息发出机制,即先prepare消息,当收到commit后消息才发出等。有兴趣可深入去研究下。

https://www.aliyun.com/product/ons?spm=5176.8142029.cloudEssentials.80.e9396d3ehA6Jv5

 

总结:

没有最好的技术,只有最合适的技术。这三种方案适用的场景都不一样。对于并发不高,对资源层通常是数据库均由访问权限的分布式系统,建议采用Spring JTA + DB XA方案。对于并发不高,互相独立的分布式系统,建议采用TCC方案。对于并发高的分布式系统,建议考虑消息队列方案。

 

引用:

https://www.cnblogs.com/savorboard/p/distributed-system-transaction-consistency.html

https://blog.csdn.net/u010412301/article/details/78410933

 

图片来源网络,侵删

, 1, 0, 9);