分布式事务看这一篇就够了

1、事务是数据库的概念

分布式事务的产生,是由于数据库的拆分和分布式架构(微服务)带来的,在常规情况下,我们在一个进程中操作一个数据库,这属于本地事务,如果在一个进程中操作多个数据库,或者在多个进程中操作一个或多个数据库,就产生了分布式事务;

(1)数据库分库分表就产生了分布式事务;

分布式事务看这一篇就够了

(2)项目拆分服务化也产生了分布式事务;

分布式事务看这一篇就够了

2、X/OpenDTP分布式事务处理参考模型

全称X/Open Distributed Transaction Processing Reference Model,即分布式事务处理参考模型;

X/Open是一个组织机构,它定义出的一套分布式事务处理的标准和规范,具体实现由不同厂商来实现;

Java EE 遵循了X/open DTP规范,设计并实现了Java里面的分布式事务编程接口规范JTA;

XA是X/Open DTP定义的中间件与数据库之间的接口规范,主流的数据库厂商都实现了XA接口函数规范;

3、分布式方案的分类

1、XA 方案

2、TCC 方案

3、本地消息异步确认

4、可靠消息最终一致性

5、最大努力通知

4、五种分布式方案的介绍

1、XA方案

XA方案即两阶段提交(Two Phase Commit),有一个事务管理器(协调者),负责协调多个数据库(资源管理器)的事务,事务管理器先询问各个数据库是否已经准备好?如果每个数据库都已就绪,那么就正式提交事务,在各个数据库上执行操作,如果任何其中一个数据库未就绪,那么就回滚事务;

这种分布式事务方案,比较适合单体应用中跨多个数据库的分布式事务,依赖于数据库层面来实现分布式事务,效率较低,不适合高并发的场景;

在分布式微服务中,一个大的系统被拆分为几十个甚至几百个服务,标准规范的做法是每个服务只操作自己对应的一个数据库,如果要操作别的服务所对应的数据库,不允许直接连接而是通过调用别人的服务接口来实现,不能交叉去访问别人的数据库,避免一些混乱的问题,比如数据被别人修改出错,或者数据库被别的服务压垮等情况;

XA的实现方案:

(1)在Java中具体实现可以采用 Spring + JTA 解决;

(2)Atomikos https://www.atomikos.com 

(3)Bitronix(btm) https://github.com/bitronix 

(4)JOTM http://jotm.objectweb.org 比较老了

 

TCC 补偿方案

TCC 的全称是:Try、Confirm、Cancel,这个也就是我们经常听到的三阶段提交;

Try 阶段:尝试执行,对各个服务的资源做检测以及对资源进行锁定或者预留;

Confirm 阶段:确认执行真正执行业务,在各个服务中执行实际的操作;

Cancel 阶段:如果任何一个服务的业务方法执行异常,那么就进行补偿,把已经执行成功的业务操作进行回滚;

该方案一般用于与支付交易相关的场景,用 TCC严格保证分布式事务要么全部成功,要么全部自动回滚,严格保证资金交易的正确性,其他场景下一般很少采用该方案,因为该方案的事务回滚是依赖于我们自己编写的业务代码来回滚和补偿,对业务代码的侵入性比较强,增加了代码的复杂度,另外最好是各个业务执行的时间都比较短;

(一般与钱打交道的,可以采用该方案)

开源的tcc实现框架

tcc-transaction  https://github.com/changmingxie/tcc-transaction 

Bytetcc  https://github.com/liuyangming/ByteTCC (https://www.bytesoft.org)

 

本地消息异步确保

本地消息异步确保是 ebay 提出来的一套分布式事务解决方案;

具体实现方案是:

A系统在自己本地一个事务里操作时,先插入一条数据到本地消息表,然后A系统将这个消息发送到消息中间件MQ中;

B系统接收到消息之后,在一个事务里,往自己本地消息表里插入一条数据,同时执行其他的业务操作,如果这个消息已经被处理过了,那么此时这个事务会回滚,这样保证不会重复处理消息;

B系统执行成功之后,就会更新自己本地消息表的状态

以及 A 系统消息表的状态(通过zookeeper或者调用a系统的接口来更新A系统的消息表状态);

如果 B 系统处理失败了,那么就不会更新消息表状态,那么此时 A 系统起一个后台线程定时扫描自己的本地消息表,如果有未处理的消息,会再次发送消息到 MQ 中,让 B 再次处理;

这个方案保证了最终一致性,哪怕 B 事务失败了,但是 A 会不断重发消息,直到 B 那边成功为止;

这个方案的不足就在于严重依赖于数据库的消息表来管理事务,数据库的性能是大的瓶颈,所以在高并发场景下,该方案不被采用,在国内我们对该方案进行了升级,就是下面的可靠消息最终一致性方案;

分布式事务看这一篇就够了

可靠消息最终一致性方案(国内互联网)

该方案是本地消息异步确保方案的升级和优化,该方案中去掉了本地消息表;

分布式事务看这一篇就够了

该方案是ebay改进版,可以适用高并发场景;(用得比较多)

 分布式事务看这一篇就够了

最大努力通知方案(也是保证最终一致性)

该方案的具体实现是:

系统 A 本地事务执行完之后,发送个消息到 MQ;

同时有一个专门消费 MQ 最大努力通知服务,该服务会消费 MQ 消息然后写入数据库中,或者是放入缓存中,然后调用系统 B 的接口;

要是系统 B 执行成功就执行完毕,如果系统 B 执行失败,那么最大努力通知服务将定时尝试重新调用系统 B,反复多次,尝试多次后如果依然失败则放弃。

(这时候 可以监控、业务后台处理,人工干预等)

 

比如在支付业务,通知支付结果通常采用该方案;

另外可以根据不同的业务定制不同的通知规则,比如通知支付结果等相对严谨的业务,可以将通知频率设置高一些,通知时间长一些,比如隔 5 分钟通知一次,持续时间 1 小时;

如果不重要的业务,比如通知用户增加积分,则可以将通知频率设置低一些,时间短一些,比如 10 分钟通知一次,持续 30 分钟。

 

 

分布式事务看这一篇就够了

扫一扫 关注我们吧~