天天看点

分布式事务初探索一、前言二、分布式事务理论三、分布式事务的解决方案四、分布式框架——seata

一、前言

传统的一个工程内为了保证数据的一致性,使用本地事务。本地事务只能解决同一工程中的事务问题,而现在的场景更加复杂,关系到两个工程模块,怎么保证要么都成功,要么都失败?分布式事务就是一次大的操作由不同的小操作组成,这些小的操作分布在不同的服务器上,且属于不同的应用,分布式事务需要保证这些小操作要么全部成功,要么全部失败。

分布式事务通常有以下三种场景:不同应用相同数据库,相同应用不同数据库,不同应用不同数据库。而分布式事务产生的原因非常多样:分布式系统异常除了本地事务那些异常之外,还有:机器宕机、网络异常、消息丢失、消息乱序、数据错误、不可靠的TCP、存储数据丢失…

分布式事务初探索一、前言二、分布式事务理论三、分布式事务的解决方案四、分布式框架——seata

数据库的 ACID 四大特性,已经无法满足我们分布式事务,这个时候又有一些新的大佬提出一些新的理论。

二、分布式事务理论

2.1 CAP理论

CAP定理是由加州大学伯克利分校Eric Brewer教授提出来的,他指出WEB服务无法同时满足一下3个属性:

  1. Consistency(一致性):在分布式系统中的所有数据备份,在同一时刻是否同样的值。

    对于数据分布在不同节点上的数据来说,如果在某个节点更新了数据,那么在其他节点如果都能读取到这个最新的数据,那么就称为强一致,如果有某个节点没有读取到,那就是分布式不一致。

  2. Availability(可用性):在集群中一部分节点故障后,集群整体是否还能响应客户端的读写请求。(要求数据需要备份)
  3. Partition tolerance(分区容忍性):大多数分布式系统都分布在多个子网络。每个子网络就叫做一个区(partition)。分区容错的意思是,区间通信可能失败。

CAP理论就是说在分布式存储系统中,最多只能实现上面的两点。而由于当前的网络硬件肯定会出现延迟丢包等问题,所以分区容忍性是我们无法避免的。所以我们只能在一致性和可用性之间进行权衡,没有系统能同时保证这三点。要么选择CP、要么选择AP。

所以接下来要讲的Base理论就是CAP的妥协方案,追求的是AP

2.2 Base

BASE是对CAP中一致性和可用性权衡的结果,其来源于对大规模互联网系统分布式实践的结论,是基于CAP定理逐步演化而来的,其核心思想是即使无法做到强一致性(Strong consistency),但每个应用都可以根据自身的业务特点,采用适当的方式来使系统达到最终一致性(Eventual consistency)。接下来看看BASE中的三要素:

  1. Basically Available(基本可用)

    基本可用是指分布式系统在出现故障的时候,允许损失部分可用性,即保证核心可用。

    电商大促时,为了应对访问量激增,部分用户可能会被引导到降级页面,服务层也可能只提供降级服务。这就是损失部分可用性的体现。

  2. Soft state(软状态)

    软状态是指允许系统存在中间状态,而该中间状态不会影响系统整体可用性。分布式存储中一般一份数据至少会有三个副本,允许不同节点间副本同步的延时就是软状态的体现。mysql replication的异步复制也是一种体现。

  3. Eventually consistent(最终一致性)

    最终一致性是指系统中的所有数据副本经过一定时间后,最终能够达到一致的状态。弱一致性和强一致性相反,最终一致性是弱一致性的一种特殊情况。

BASE模型是传统ACID模型的反面,不同于ACID,BASE强调牺牲高一致性,从而获得可用性,数据允许在一段时间内的不一致,只要保证最终一致就可以了。

既然我们已经有了分布式理论的支撑,下面让我们来看看对于分布式事务有什么样的解决方案。

三、分布式事务的解决方案

在介绍解决方案之前,我们需要先清楚三种一致性的概念。强一致性是指写完之后立马可以读到最新数据,弱一致性允许存在中间状态,最终一致性是弱一致性的特殊情况(不知道中间状态会存在多久,但最终会达到一致性)。

3.1 2PC两阶段提交

2PC即两阶段提交协议,是将整个事务流程分为两个阶段,准备阶段(Prepare phase)、提交阶段(commit phase),2是指两个阶段,P是指准备阶段,C是指提交阶段。

分布式事务初探索一、前言二、分布式事务理论三、分布式事务的解决方案四、分布式框架——seata

第一阶段:事务协调器要求每个涉及到事务的数据库预提交(precommit)此操作,并反映是否可以提交.

第二阶段:事务协调器要求每个数据库提交数据。

其中,如果有任何一个数据库否决此次提交,那么所有数据库都会被要求回滚它们在此事务中的那部分信息。

XA 协议是一个两阶段提交协议,又叫做 XA Transactions。目前主流数据库大多支持XA协议,MySQL从5.5版本开始支持,SQL Server 2005 开始支持,Oracle 7 开始支持。

XA协议比较简单,而且一旦商业数据库实现了XA协议,使用分布式事务的成本也比较低。但是,XA也有致命的缺点,那就是性能不理想,特别是在交易下单链路,往往并发量很高,XA无法满足高并发场景。总结来说有以下缺点:

  1. 两阶段提交涉及多次节点间的网络通信,通信时间太长!
  2. 事务时间相对于变长了,锁定的资源的时间也变长了,造成资源等待时间也增加好多。
  3. XA目前在商业数据库支持的比较理想,在mysql数据库中支持的不太理想,mysql的XA实现,没有记录prepare阶段日志,主备切换会导致主库与备库数据不一致。许多nosql也没有支持XA,这让XA的应用场景变得非常狭隘。

3.2 TCC补偿性事务

是一种编程式分布式事务解决方案。

TCC 其实就是采用的补偿机制,其核心思想是:针对每个操作,都要注册一个与其对应的确认和补偿(撤销)操作。TCC模式要求从服务提供三个接口:Try、Confirm、Cancel。

  • Try:主要是对业务系统做检测及资源预留
  • Confirm:真正执行业务,不作任何业务检查;只使用Try阶段预留的业务资源;Confirm操作满足幂等性。
  • Cancel:释放Try阶段预留的业务资源;Cancel操作满足幂等性。

整个TCC业务分成两个阶段完成:

分布式事务初探索一、前言二、分布式事务理论三、分布式事务的解决方案四、分布式框架——seata

第一阶段:主业务服务分别调用所有从业务的try操作,并在活动管理器中登记所有从业务服务。当所有从业务服务的try操作都调用成功或者某个从业务服务的try操作失败,进入第二阶段。

第二阶段:活动管理器根据第一阶段的执行结果来执行confirm或cancel操作。如果第一阶段所有try操作都成功,则活动管理器调用所有从业务活动的confirm操作。否则调用所有从业务服务的cancel操作。

举个例子,假如 Bob 要向 Smith 转账100元,思路大概是:

我们有一个本地方法,里面依次调用

  1. 首先在 Try 阶段,要先检查Bob的钱是否充足,并把这100元锁住,Smith账户也冻结起来。
  2. 在 Confirm 阶段,执行远程调用的转账的操作,转账成功进行解冻。
  3. 如果第2步执行成功,那么转账成功,如果第二步执行失败,则调用远程冻结接口对应的解冻方法 (Cancel)。

缺点:

  • Canfirm和Cancel的幂等性很难保证。
  • 这种方式缺点比较多,通常在复杂场景下是不推荐使用的,除非是非常简单的场景,非常容易提供回滚Cancel,而且依赖的服务也非常少的情况。
  • 这种实现方式会造成代码量庞大,耦合性高。而且非常有局限性,因为有很多的业务是无法很简单的实现回滚的,如果串行的服务很多,回滚的成本实在太高。

3.3 MQ最终一致性

基于消息中间件的两阶段提交往往用在高并发场景下,将一个分布式事务拆成一个消息事务(A系统的本地操作+发消息)+B系统的本地操作,其中B系统的操作由消息驱动,只要消息事务成功,那么A操作一定成功,消息也一定发出来了,这时候B会收到消息去执行本地操作,如果本地操作失败,消息会重投,直到B操作成功,这样就变相地实现了A与B的分布式事务。

分布式事务初探索一、前言二、分布式事务理论三、分布式事务的解决方案四、分布式框架——seata

虽然上面的方案能够完成A和B的操作,但是A和B并不是严格一致的,而是最终一致的,我们在这里牺牲了一致性,换来了性能的大幅度提升。当然,这种玩法也是有风险的,如果B一直执行不成功,那么一致性会被破坏,具体要不要玩,还是得看业务能够承担多少风险。

综上所述,三种解决方案各有优缺点,要结合具体的场景来使用。如果要追求一致性,最好选择2PC方案,如果要追求极致性能,就可以选择MQ最终一致性方案。

下面我们介绍以下阿里的分布式事务框架——seata。

四、分布式框架——seata

seata(Simple Extensible Autonomous Transaction Architecture)目前支持AT模式(优化后的两阶段提交)、TCC模式。

Seata有3个基本组件:

  • Transaction Coordinator(TC):事务协调器,维护全局事务的运行状态,负责协调并驱动全局事务的提交或回滚。
  • Transaction Manager™:事务管理器,控制全局事务的边界,负责开启一个全局事务,并最终发起全局提交或全局回滚的决议。
  • Resource Manager(RM):资源管理器,控制分支事务,负责分支注册、状态汇报,并接收事务协调器的指令,驱动分支(本地)事务的提交和回滚。
分布式事务初探索一、前言二、分布式事务理论三、分布式事务的解决方案四、分布式框架——seata

全局事务与分支事务:

a Distributed Transaction is a Global Transaction which is made up with a batch of Branch Transaction, and normally Branch Transaction is just Local Transaction.

分布式事务初探索一、前言二、分布式事务理论三、分布式事务的解决方案四、分布式框架——seata

Seata管理分布式事务的典型生命周期:

  • TM 向 TC 申请开启一个全局事务,全局事务创建成功并生成一个全局唯一的 XID。
  • XID 在微服务调用链路的上下文中传播。
  • RM 向 TC 注册分支事务,将其纳入 XID 对应全局事务的管辖。
  • TM 向 TC 发起针对 XID 的全局提交或回滚决议。
  • TC 调度 XID 下管辖的全部分支事务完成提交或回滚请求。
分布式事务初探索一、前言二、分布式事务理论三、分布式事务的解决方案四、分布式框架——seata

至此,seata的协议机制总体上看与 XA 是一致的。但是是有差别的:

分布式事务初探索一、前言二、分布式事务理论三、分布式事务的解决方案四、分布式框架——seata

XA 方案的 RM 实际上是在数据库层,RM 本质上就是数据库自身(通过提供支持 XA 的驱动程序来供应用使用)。

而 Fescar (seata的前身)的 RM 是以二方包的形式作为中间件层部署在应用程序这一侧的,不依赖于数据库本身对协议的支持,当然也不需要数据库支持 XA 协议。这点对于微服务化的架构来说是非常重要的:应用层不需要为本地事务和分布式事务两类不同场景来适配两套不同的数据库驱动。

这个设计,剥离了分布式事务方案对数据库在 协议支持 上的要求。

具体的整合可以参照https://github.com/seata/seata-samples/tree/master/springcloud-jpa-seata,这里就不多做介绍了。

以上,就是关于分布式事务的一些知识。

继续阅读