当前位置: 首页 > 科技观察

5种分布式事务方案优缺点对比

时间:2023-03-17 18:41:33 科技观察

背景分布式事务是企业集成中的一个技术难点,也是每一个分布式系统架构都会涉及到的东西,尤其是微服务架构,几乎可以说是不可避免的。ACID指的是数据库事务正确执行的四个基本要素:原子性、一致性、隔离性、持久性CAP原则,也称为CAP定理,是指在分布式系统中,一致性、可用性、分区容错性。CAP原则就是这三个要素最多只能同时达到两个点,不可能三者兼顾。一致性:分布式系统中的所有数据备份是否同时具有相同的值。可用性:集群中部分节点发生故障后,集群整体是否还能响应客户端的读写请求。分区容忍:就实际效果而言,分区相当于通信的时限要求。如果系统不能在时限内实现数据一致性,则意味着发生了分区,当前操作必须在C和A之间做出选择。BASE理论BASE理论是CAP中一致性和可用性之间权衡的结果。该理论的核心思想是:我们无法做到强一致性,但各个应用可以根据自己的业务特点采用合适的方法。系统实现最终一致性。BasicallyAvailable(基本可用)Softstate(软状态)Eventuallyconsistent(最终一致性)解决方案01两阶段提交(2PC)两阶段提交2PC是分布式事务中最强大的事务类型之一,两阶段提交就是它分两个阶段提交。第一阶段询问每个事务数据源是否就绪,第二阶段实际提交数据给事务数据源。为了保证事务能够满足ACID,必须引入一个协调器(Cooradinator)。其他节点称为参与者。协调器负责调度参与者的行为,并最终决定这些参与者是否应该提交事务。处理流程如下:Phase1a)协调者向所有参与者发送交易内容,询问是否可以提交交易,等待回复。b)每个参与者执行一次事务操作,在事务日志中记录undo和redo信息(但不提交事务)。c)如果参与者执行成功,则向协调者反馈yes,否则不反馈。Phase2:如果协调器收到参与者的失败消息或超时,则向每个参与者发送回滚消息;否则,它会发送一条提交消息。两种情况的处理如下:情况1:当所有参与者都反馈yes时,提交事务a)协调器向所有参与者发送正式请求提交事务(即commitrequest)。b)参与者执行提交请求并释放整个事务期间占用的资源。c)每个参与者向协调器反馈ack(响应)完成消息。d)协调器收到所有参与者反馈的ack消息后,交易提交完成。情况2:当参与者反馈否时,回滚事务a)协调器向所有参与者发送回滚请求(rollbackrequest)。b)参与者利用第一阶段的undo信息进行回滚操作,释放整个事务占用的资源。c)各参与者向协调器反馈ack完成的消息。d)协调者收到所有参与者的ack消息后,交易完成。问题1)性能问题:事务提交阶段所有参与者都处于同步阻塞状态,占用系统资源,容易造成性能瓶颈。2)可靠性问题:如果coordinator出现单点故障,或者失效,provider会一直被锁住。3)数据一致性问题:在阶段2,如果协调者和参与者都挂掉了,可能会导致数据不一致。优点:尽可能保证数据的强一致性,适用于对数据一致性要求高的关键领域。(其实并没有100%的强一致性保证)。缺点:实现复杂,牺牲可用性,对性能影响较大。不适合高并发、高性能的场景。02三阶段提交(3PC)三阶段提交是两阶段提交的改进版。3PC最主要要解决的就是协调者和参与者同时挂掉的问题,所以3PC把2PC的准备阶段一分为二,这样的三阶段提交。处理流程如下:Phase1a)协调器向所有参与者发送一个包含事务内容的canCommit请求,询问事务是否可以提交,并等待所有参与者的回复。b)参与者收到canCommit请求后,如果认为可以进行交易操作,则反馈yes,进入准备状态,否则反馈no。根据参与者的反应,第二阶段协调员有以下两种可能。Case1:所有参与者都反馈yes,协调者预执行事务a)协调者向所有参与者发送preCommit请求,进入准备阶段。b)参与者收到preCommit请求后,执行事务操作,并在事务日志中记录undo和redo信息(但不提交事务)。c)各参与者向协调器反馈ack响应或无响应,等待最终指令。情况2:只要有一个参与者反馈no,或者协调器等待超时后无法收到所有provider的反馈,事务就会中断a)协调器向所有参与者发送中止请求。b)无论接收到协调者的中止请求,还是在等待协调者请求时超时,参与者都会中止事务。Phase3在这个阶段,真正的交易提交也可以分为以下两种情况。Case1:所有参与者都反馈ack响应并执行真正的事务提交a)如果协调器正在工作,则向所有参与者发送一个doCommit请求。b)参与者收到doCommit请求后,正式执行事务提交,释放整个事务占用的资源。c)各参与者向协调器反馈ack完成的消息。d)协调器收到所有参与者反馈的ack消息后,交易提交完成。情况二:只要有一个参与者反馈no,或者协调组等待超时后无法收到所有provider的反馈,事务就会被回滚。a)如果协调者正在工作,则向所有参与者发送回滚请求。b)参与者利用第一阶段的undo信息进行回滚操作,释放整个事务占用的资源。c)各参与者向协调组反馈ack完成消息。d)协调组收到所有参与者反馈的ack消息后,事务回滚完成。优点:与两阶段提交相比,三阶段提交减少了阻塞的范围,协调者或参与者在等待超时后会中断事务。避免协调器单点问题。当第3阶段协调器出现问题时,参与者继续提交交易。缺点:数据不一致的问题依然存在。当参与者收到preCommit请求后等待docommit命令时,如果此时协调器请求中断事务,但协调器无法与参与者正常通信,则参与者会继续提交事务。导致数据不一致。03补偿事务(TCC)TCC是面向服务的两阶段编程模型,采用的补偿机制:条件:需要实现确认和补偿逻辑,需要支持幂等处理流程:a)Try阶段主要是检测业务系统和储备资源保留。该阶段主要完成:完成所有业务检查(一致性)。预留必要的业务资源(准隔离)。尝试尝试执行业务。b)Confirm阶段主要是对业务系统进行确认和提交。当Try阶段执行成功并执行Confirm阶段时,默认的Confirm阶段是没有错误的。即:只要Try成功,Confirm就一定成功。c)Cancel阶段主要是在业务执行错误需要回滚时取消业务,释放预留资源。优点:性能提升:针对具体业务降低了控制资源锁的粒度,不会锁住整个资源。数据最终一致性:基于Confirm和Cancel的幂等性,保证交易最终确认或取消,保证数据一致性。可靠性:解决了XA协议协调器的单点故障问题。主要业务方发起并控制整个业务活动。业务活动管理器也变成多点,引入集群。缺点:TCC的Try、Confirm、Cancel操作功能需要根据具体业务实现,业务耦合度高,增加开发成本。04本地消息表(消息队列)的核心思想是将分布式事务拆分成本地事务进行处理。该方案在消费者中新建一个事务消息表,消费者处理业务并在本地事务中记录事务消息,轮询事务消息表中的数据发送事务消息,提供者在事务中消费事务基于消息中间件的消息表。条件:服务消费者需要创建消息表记录消息状态。服务消费者和提供者需要支持幂等性。需要补偿逻辑。在每个节点上启动一个定时线程,检查未处理或失败的消息,并重新发送消息,即重试机制和幂等机制。处理流程:1.服务消费者将业务数据和消息一起提交,发起交易。2、消息通过MQ发送给服务提供者,服务消费者等待处理结果。3.服务提供者接收消息,完成业务逻辑并将处理后的消息通知给消费者。容错处理如下:当第1步出错时,回滚事务,相当于什么都没发生。当第2步和第3步出错时,由于消息保存在消费者表中,可以重新发送给MQ重试。如果第3步处理有错误,是业务失败,服务提供者发送消息通知消费者交易失败,此时消费者发起回滚事务执行回滚逻辑.优点:从应用设计开发的角度,实现了消息数据的可靠性。消息数据的可靠性不依赖于消息中间件,弱化了对MQ中间件特性的依赖。缺点:与特定业务场景绑定,耦合性强,不能共享。消息数据和业务数据在同一个数据库,占用业务系统资源。当业务系统使用关系型数据库时,消息服务性能会受到关系型数据库并发性能的限制。MQ事务消息(最终一致性)支持事务消息的MQ,其支持事务消息的方式类似于两阶段提交。基于MQ的分布式事务方案其实是对本地消息表的一种封装,其内部是基于MQ的,协议其他方面与本地消息表基本一致。条件:a)需要补偿逻辑b)业务处理逻辑需要幂等处理流程:c)消费者向MQ发送一半消息。d)MQServer持久化消息后,向senderack确认消息发送成功。e)消费者开始执行交易逻辑。f)消费者根据本地事务的执行结果向MQServer提交二次确认或回滚。g)MQServer在收到提交状态时将半消息标记为可交付。h)服务提供者接收消息并执行本地业务逻辑。返回处理结果。优点:消息数据独立存储,降低了业务系统与消息系统的耦合度。吞吐量优于本地消息表方案。缺点:发送一条消息需要两次网络请求(半条消息+commit/rollback)。需要实现消息回传接口。05Sagas事务模型(最终一致性)Saga模式是分布式异步事务,最终一致性事务,灵活事务。有两种不同的方式来实现传奇交易。最流行的两种方式是:1.事件/编排编排:当没有中央协调器(没有单点风险)时,每个服务生成并侦听来自其他服务的事件,并决定是否应该采取行动。该实现首先执行事务,然后发布事件。该事件由一个或多个执行本地事务并发布(或不发布)新事件的服务侦听。当最后一个服务执行本地事务并且没有发布任何事件时,这意味着分布式事务结束,或者它发布的任何saga参与者都没有听到的事件表示事务结束。处理流程:订单服务保存新订单,设置状态为pending状态,并发布一个名为ORDER_CREATED_EVENT的事件。支付服务监听ORDER_CREATED_EVENT并发布事件BILLED_ORDER_EVENT。库存服务侦听BILLED_ORDER_EVENT、更新库存并发布ORDER_PREPARED_EVENT。货运服务侦听ORDER_PREPARED_EVENT,然后交付产品。最后,它发布ORDER_DELIVERED_EVENT。最后,订单服务监听ORDER_DELIVERED_EVENT并将订单状态设置为已结束。假设库存服务在交易期间失败。回滚:库存服务产生PRODUCT_OUT_OF_STOCK_EVENT订单服务,支付服务会监听以上库存服务的这个事件:①支付服务将退款给客户。②订单服务设置订单状态为失败。优点:事件/编排是实现Saga模式的自然方式;它很简单,易于理解,不需要太多努力来构建,并且所有参与者都是松散耦合的,因为它们彼此之间没有直接耦合。如果您的交易涉及2到4个步骤,它可能很适合。2.Command/coordinationorchestrator:中央协调器负责集中处理事件的决策和业务逻辑排序。saga协调器Orchestrator以命令/回复的方式与每个服务通信,告诉它们应该执行什么操作。订单服务保存pending状态,并请求OrderSagaCoordinator(简称OSO)启动订单交易。OSO向收款服务发送支付执行命令,收款服务回复PaymentExecuted消息。OSO向库存服务发送PrepareOrder命令,库存服务将回复OrderPrepared消息。OSO向货运服务发送订单交付命令,货运服务将回复OrderDelivered消息。OSO订单Saga协调员必须事先知道执行“创建订单”事务所需的流程(通过读取BPM业务流程XML配置获得)。它还负责协调分布式回滚,方法是向每个参与者发送命令以在任何失败时撤消先前的操作。当你有一个协调一切的中央协调器时,回滚就容易多了,因为协调器默认做正向流,而当你回滚时,你只是做反向流。优点:避免服务之间的循环依赖,因为saga协调器调用sagaactor,但actor不调用协调器。集中式分布式事务的编排。它只需要执行命令/回复(其实回复消息也是一种事件消息),降低了参与者的复杂度。随着新步骤的添加,事务复杂性保持线性,并且回滚更易于管理。如果你想在第一个事务执行之前改变第二个事务的目标对象,你可以很容易地将它挂在协调器上,直到第一个事务完成。