3.11:分布式事务

2020-05-23  本文已影响0人  今年花开正美

​本文将梳理微服务架构下,分布式事务的常用方案。整体包含以下三部分:

分布式事务的提出

数据库事务

事务概念

事务一般指数据库事务,数据库事务是访问并可能操作各种数据项的一个 数据库操作序列,这些操作 要么全部执行,要么全部不执行。是一个 不可分割的工作单元。事务由事务开始和事务结束之间的全部数据库操作组成。

ACID特性

隔离性

要理解事务隔离性,首先需要了解事务的并发问题:

  1. 脏读:事务A读取了事务B未提交的数据,然后事务B回滚,那么事务A读取到的数据是脏数据。

  2. 不可重复的:事务A多次读取同一数据,事务B在事务A多次读取过程中,对数据做了更新并提交,导致事务A多次读取同一数据时,出现不一致性。

  3. 幻读:事务A在第二次查询时,读到了事务B新提交的数据。

隔离级别 脏读 不可重复的 幻读
读未提交
不可重复读
可重复读
串行化

分布式事务

场景驱动

微服务架构下,数据分散在多个存储中,此时无法使用传统的数据库事务,就需要分布式事务来保证多个存储的数据一致性。

image

分布式事务主流方案

说到分布式场景的问题,基本上都绕不开CAP定理,我们先对CAP定理有个基本的概念。

CAP定理

CAP定理是指,在分布式系统中,一致性(Consistency)、可用性(Availability)、分区容错性(Partition tolerance)。这三个要素只能满足其中的两个,不可能三者兼顾。

一般而言分布式事务都是实现多个数据库之间的事务一致性,因此分布式事务要满足的就是CAP定理中的CP,也就是保证网络分区下的强一致性。

但若系统追求强CP,那在出现网络分区时,就必须牺牲系统的可用性。因此基于CP之上,又提出了数据的最终一致性理论,比如Base、Saga等。

分布式事务分类

基于上述理论之上,目前的主流的分布式事务可以分为强一致性和弱一致性(最终一致性)。

下面我们针对上述的分布式一致性方案逐个详细梳理。

强一致性

强一致性的核心思想是,所有事务在提交/回滚阶段,必须保证成功提交/回滚,也就是多个事务必须是同时提交成功或回滚成功。只要有一个事务未完成提交或回滚,分布式事务都不能结束。

理论模型:XA模型

XA模型主要由三部分组成,事务管理器(TM)、资源管理器(RM)、应用程序(AM)。

image

2PC

XA模型只是规范,2PC是基于XA模型的实现。2PC整体分为两个阶段:准备、提交。

第一阶段(准备):

  1. 事务管理器TM向所有应用程序AP发prepare消息。

  2. 应用程序AP收到表决请求后,执行本地事务,写redo日志和undo日志,但不提交事务。

  3. 应用程序AP向事务管理器TM响应结果ACK(提交或回滚)。

若事务管理器TM收到所有的ACK都是OK,则进行第二阶段的事务提交,只要有一个ACK是NO,则进行第二阶段的回滚。

第二阶段(提交)

  1. 事务管理器TM向所有的应用程序AP发送事务提交(commit)请求。

  2. 应用程序收到提交请求后,读取redo日志,完成本地事务的提交。

  3. 应用程序AP向事务管理器TM响应提交结果。

第二阶段(回滚)

  1. 事务管理器TM向所有的应用程序AP发送事务提交(rollback)请求。

  2. 应用程序收到提交请求后,读取undo日志,完成本地事务的回滚。

  3. 应用程序AP向事务管理器TM响应回滚结果。

注意:在第二阶段执行中是不可逆的,要求所有事务都必须完成提交或回滚,若提交或回滚失败,本地事务需重新恢复继续提交或回滚,直到成功为止。

2PC主要有如下两个较大的缺点:

  1. 同步阻塞过长,整个分布式事务执行过程中所有AP都是同步等待的。

  2. TM单点问题,若当AP即将进入第二阶段时,TM故障,AP将一直等待阶段,无法进入commit。

3PC

3PC是在2PC基础上,将2PC的第一阶段拆分为两个阶段,是2PC的改进版。

第一阶段(canCommit)

  1. 事务管理器TM向所有的应用程序AP发送canCommit消息。

  2. 应用程序收到canCommit请求后,检查本地事务链接、权限等,确定是否可以执行事务。

  3. 应用程序AP向事务管理器TM响应检查结果。

若事务管理器TM收到所有的应用程序AP的canCommit响应都是OK,则进入第二阶段,否则直接取消分布式事务。

第二阶段(preCommit)

  1. 事务管理器TM向所有应用程序AP发preCommit消息。

  2. 应用程序AP收到表决请求后,执行本地事务,写redo日志和undo日志,但不提交事务。

  3. 应用程序AP向事务管理器TM响应结果ACK(提交或回滚)。

第三阶段,与2PC的第二阶段是一样的,就不再累述。

3PC相较2PC主要有两个改进,减少阻塞(增加了canComit),应用程序增加了超时自动commit。但同步性能问题仍然未解决。

弱一致性(最终一致性)

弱一致性的核心思想是,将一个分布式事务拆分为多个本地事务,若在本地事务执行过程中出现异常,则执行补偿来保证数据能最终一致。

弱一致性根据事务的执行方式,又可以分为同步模型和异步模型。同步是指多个事务执行是同步的,也就是由同一个线程来协调/编排事务提交。异步是指每个事务的提交和补偿是由本地事务自己来完成的。

同步模型

目前常用的同步模型主要是TCC和Saga。

TCC

TCC核心思想是,先对所需资源进行锁定或申请,若锁定成功,则执行提交,若锁定失败则对锁定资源进行释放。

TCC模型要求所有应用程序都要实现try、confirm、cancle三个方法:

关于TCC服务器故障时:

  1. 若在try过程中有部分机器故障,协调器需要根据记录的已执行try的事务,并调相应的cancle方法完成资源释放。

  2. 若confirm、cancle阶段有机器故障,协调性不断的重新发起confirm、cancle的调用。

Saga

Saga将分布式事务拆分为一系列的本地事务T1,T2,T3,...,Tn,每个本地事务提供相应的补偿动作C1,C2,C3,...,Cn. Saga保证分布式事务执行顺序为:

  1. T1,T2,T3,...,Tn

  2. T1,T2,T3,...,Tj,Cj-1,...,C1

同时,Saga定义了两种恢复策略:

业务中基本上使用的都是T1,T2,T3,...,Tj,Cj-1,...,C1的执行顺序。

image

异步模型

异步模型即为将分布式事务下的服务同步调用异步化,比如原有的调用为A->B->C,异步化后为:业务调用->A->MQ,MQ->B->MQ,MQ->C。

异步化后,只需要保证MQ消息的可靠性,也就是说需要保证本地事务执行成功后MQ一定能发送成功。

消息的可靠性可借助事务消息组件和本地消息表。

事务消息(RocketMQ)

RocketMQ相较于其他MQ主要有以下改进来保证消息的可靠传递:

  1. 支持“半消息”,业务方(生产者)在执行本地事务前,需先向RocketMQ发送“半消息”,此时的消息处于“暂不投递”状态,需要业务方(生产者)在执行完本地事务后发送二次确认才进行投递。

  2. 业务提供消息“回查”功能,为了防止业务方(生产者)在发送“半消息”后系统故障,RocketMQ会对长期处于“暂不投递”状态的消息,调用业务方(生产者)提供回查接口来决定是否投递。

  3. “消费者”在消息重复发送时需要保证幂等性。

image
本地消息表

事务消息的缺点是,目前只有RocketMQ支持事务消息,对技术选型有限制。因此,基于事务消息来改造,将消息和业务数据表的强一致性使用本地事务来保证。

  1. 在业务服务数据库中创建消息表,将业务和消息保存放到同一个本地事务中。

  2. 基于业务服务数据库启动独立的msgClient,不断轮询消息表,将本地消息表中未发送成功(待发送、发送失败、发送超时)的消息发送给MQ组件。

  3. 对发送成功(接收到ACK响应)的消息进行删除,

  4. “消费者”在消息重复发送时需要保证幂等性。

image

分布式事务选择

如何选择分布式事务方案

可以将业务按CAP定理来分析,业务是需要满足CP,还是AP。

若业务必须满足CP(强一致性),且接受一定的性能损耗,则使用3PC。

若业务为AP(最终一致性),只要业务能保证最终一致性即可,此时又需要分析业务是使用同步模型还是异步模型。若是同步模型则选择Saga,若异步则建议使用本地消息表。因TCC和事务消息都需要业务方来改造支持。

上一篇下一篇

猜你喜欢

热点阅读