互联网领域的大部分系统都采用SOA、微服务化的架构。一个涉及端到端全链路的业务操作往往会由多个服务和数据库实例共同完成。因此,在一致性要求较高的业务场景中,如何保证多个服务之间RPC调用后的数据一致将成为关键点。现状是分布式事务一直是痛点,也是难点。

社区里也有一些开源的分布式解决方案的框架,比如ByteTCC、LCN,但是这些框架没有一个权威的组织在维护。好在19年初阿里分布式事务框架GTS开源了一个免费社区版Fescar项目地址:https://github.com/alibaba/fescar

分布式事务是一个全局事务,由一批Branch Transation组成,通常Branch Transation只是本地事务。

微服务 怎么避免 分布式事务 微服务的分布式事务_微服务 怎么避免 分布式事务


在FESACR项目中有3个基本组件:

  • 事务协调员(TC):维护全局和分支事务的状态,推动全局提交或回滚。
  • 事务管理者(TM):定义全局事务的范围:开始全局事务,提交或回滚全局事务。
  • 资源管理器(RM):管理分支事务处理的资源,与TC通信以注册分支事务和报告分支事务的状态,并驱动分支事务提交或回滚。
分布式系统
CAP特点:

a.一致性(Consistency)😦 同样数据在分布式系统的各个节点上都是一致的)
b.可用性(Availability)😦 所有在分布式系统活跃的节点都能够处理操作且能响应查询)
c.分区容忍性(Partition Tolerance) :(如果出现了网络故障、一部分节点无法通信,但是系统仍能够工作)

ACID特点:

a.原子性(Atomicity)

一个事务(transaction)中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节。事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。

b.一致性(Consistency)

事务的一致性指的是在一个事务执行之前和执行之后数据库都必须处于一致性状态。如果事务成功地完成,那么系统中所有变化将正确地应用,系统处于有效状态。如果在事务中出现错误,那么系统中的所有变化将自动地回滚,系统返回到原始状态。

c.隔离性(Isolation)

指的是在并发环境中,当不同的事务同时操纵相同的数据时,每个事务都有各自的完整数据空间。由并发事务所做的修改必须与任何其他并发事务所做的修改隔离。事务查看数据更新时,数据所处的状态要么是另一事务修改它之前的状态,要么是另一事务修改它之后的状态,事务不会查看到中间状态的数据。

d.持久性(Durability)

指的是只要事务成功结束,它对数据库所做的更新就必须永久保存下来。即使发生系统崩溃,重新启动数据库系统后,数据库还能恢复到事务成功结束时的状态。

RocketMQ中间件能够支持一种事务消息机制

确保本地操作和发送消息的异步处理达到本地事务的结果一致。
第一阶段,RocketMQ在执行本地事务之前,会先发送一个Prepared消息,并且会持有这个消息的接口回查地址。
第二阶段,执行本地事物操作。
第三阶段,确认消息发送,通过第一阶段拿到的接口地址URL执行回查,并修改状态,如果本地事务成功,则修改状态为已提交,否则修改状态为已回滚。

2PC协议

二阶段提交协议是分布式系统中较为经典的处理数据一致性的解决方案

第一阶段:称为准备(prepare)阶段。

事务协调者向各个服务应用发送prepare请求,服务应用在得到请求后做预处理操作,预处理可能是做预检查,也可能是把请求临时存储,可以理解为是一种试探性地提交。下面是一般的步骤:

a.事务协调者会问所有的参与者服务,是否可以提交操作。
b.各个参与者开始事务执行的准备工作:如资源上锁,预留资源,写回滚/重试的log。
c.参与者响应协调者,如果事务准备工作成功,则回应“可以提交”,否则回应拒绝提交。

第二阶段:称为提交(commit)/回滚(rollback)阶段。

是指事务真正提交或者回滚的阶段。如果事务协调者发现事务参与者有一个在prepare阶段出现失败,则会要求所有的参与者进行回滚。如果协调者发现所有的参与者都prepare操作都是成功,那么他将向所有的参与者发出提交请求,这时所有参与者才会正式提交。由此保证了要求全部提交成功,要么全部失败。下面是具体步骤:

a.如果所有的参与者都回应“可以提交”,那么协调者向所有参与者发送“正式提交”的命令。参与者完成正式提交,并释放所有资源,然后回应“完成”,协调者收集各个服务的“完成”回应后结束事务。
b.如果有一个参与者回应“拒绝提交”,那么协调者向所有的参与者发送“回滚操作”,并释放所有的资源,然后回应“回滚完成”,协调者收集各个服务应用的“回滚”返回后,取消整体的分布式事务。

下图为二阶段的成功和失败示例图:

微服务 怎么避免 分布式事务 微服务的分布式事务_分布式事务_02

二阶段提交协议其原理简单,但缺点也是存在,主要缺点如下:

a.单点问题:协调者在整个二阶段中的作用非常重要,一旦部署协调者组件服务的节点出现不可用宕机情况,那么会影响整个分布式系统的正常运行。
b.同步阻塞:二阶段提交执行过程中,所有服务参与者需要服从协调者的统一调度,期间处于阻塞状态,会一定程度上影响整个系统的效率。

本地消息
原理

本地消息表与业务数据表处于同一个数据库中,这样就能利用本地事务来保证在对这两个表的操作满足事务特性。

过程

1.在分布式事务操作的一方,它完成写业务数据的操作之后向本地消息表发送一个消息,本地事务能保证这个消息一定会被写入本地消息表中。
2.之后将本地消息表中的消息转发到 Kafka 等消息队列(MQ)中,如果转发成功则将消息从本地消息表中删除,否则继续重新转发。
3.在分布式事务操作的另一方从消息队列中读取一个消息,并执行消息中的操作。

总结

本地消息表利用了本地事务来实现分布式事务,并且使用了消息队列来保证最终一致性。