分布式事务

事务四大特性ACID
A:原子性(Atomicity),一个事务(transaction)中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节。

C:一致性(Consistency),事务的一致性指的是在一个事务执行之前和执行之后数据库都必须处于一致性状态。

I:隔离性(Isolation),指的是在并发环境中,当不同的事务同时操纵相同的数据时,每个事务都有各自的完整数据空间。

D:持久性(Durability),指的是只要事务成功结束,它对数据库所做的更新就必须持久化保存下来。

我们目前数据库事务和隔离级别采用注解的方式定义:

// An highlighted block
@Transactional (propagation = Propagation.REQUIRED)
    public void addLmtAccountInfo(LmtAccountInfo lmtAccountInfo) {
        this.checkAcctInfoForAdd(lmtAccountInfo);

微服务下事务原子性的问题
微服务框架下,一个大的操作可能会分散到不同的微服务进行处理,目前的数据库事务的机制无法保证跨服务事务的原子性,有可能最终A服务对数据的操作成功,而B服务对数据的操作失败。

例如,我司CTS和NCC在借款操作中,确认打款成功后,NCC会更新状态、生成还款计划,CTS也会更新状态、额度等,按理这些应该是一个大的事务,但是由于跨服务目前无法做成一个事务,还偶现两边状态不一致的问题。

本质上来说,分布式事务就是为了保证不同数据库的数据一致性。其它场景举例:
分布式事务_第1张图片
分布式事务_第2张图片

解决方式一:服务聚合
服务聚合模式是最常用的服务组合模式,它根据业务流程处理的需要,以一定的顺序调用依赖的多个微服务,对依赖的微服务返回的数据进行组合、加工和转换,最后以一定的形式返回给使用方。

采用服务聚合的方式是解决分布式事务的一种方式,聚合服务通过本地事务的方式保证事务的原子性,但是往往会涉及复杂的数据剥离或数据同步的机制;
分布式事务_第3张图片
解决方式二:XA协议及二阶段提交
MySQL 从5.0.3开始支持XA协议,通过二阶段提交的方式实现分布式的事务。下面是典型的XA事务的举例:(只有举例了单个数据库分支,其它数据库分支类似)
分布式事务_第4张图片
基于XA协议的二阶段提交示意:
分布式事务_第5张图片
二阶段提交的方式,可以比较好的解决同一服务对多个数据库操作的分布式事务的问题,但是对于不同的微服务操作不同的数据库并不适用,此时可以通过服务聚合和二阶段提交结合的方式进行解决。

解决方式三:应用层补偿
TCC编程模式:

l Try 阶段:尝试执行,完成所有业务检查(一致性),预留必需业务资源(准隔离性)。

l Confirm 阶段:确认真正执行业务,不作任何业务检查,只使用 Try 阶段预留的业务资源,Confirm 操作满足幂等性。要求具备幂等设计,Confirm 失败后需要进行重试。

l Cancel 阶段:取消执行,释放 Try 阶段预留的业务资源,Cancel 操作满足幂等性。Cancel 阶段的异常和 Confirm 阶段异常处理方案基本上一致。

状态+定时任务补偿:

通过状态记录事务走到哪一步,通过定时任务推动事务向下一步走;Ebay采用这种方式,我司也可理解为这种方式

解决方式四:基于MQ事务
RocketMQ提供了MQ事务的功能用于支持分布式事务,我司目前未使用该机制;
分布式事务_第6张图片
该机制保证了消息生产者若事务成功,则消息必然会发送出去,若事务失败,则消息必然发不出去。

注意:消息消费者的事务成功,由消费者自己去保证,不提供消费失败后回滚生产者事务的机制。

你可能感兴趣的:(分布式事务)