分布式事务系列之常见解决方案

在上一个文章,我们讲了CAP理论:CA和CP,但是在电商领域等互联网场景下,基于CP的强一致性方案在数据库性能和系统处理能力上会有一定的瓶颈,所以平常更多采用的是遵循BASE理论的柔性事务来实现的事务模型,柔性事务主要有两个特性:基本可用、柔性状态,对于这两个特性,我们讲一下常见解决方案


1、TCC补偿型方案

TCC相对来说是一种比较成熟的分布式数据一致性解决方案,他实际上是把一个完整的业务拆分为下面三个步骤:

  • Try:这个阶段主要是对数据的校验或者资源的预留
  • Confirm:确认真正执行的任务,值操作Try阶段预留的资源
  • Cancel:取消执行,释放Try阶段预留的资源

TCC实质上是一种两阶段提交,第一阶段通过Try进行准备工作,第二阶段Confirm/Cancel标识Try阶段操作的确认和回滚

逻辑主要思想: 在分布式场景下,每个服务实现TCC之后,就作为其中的一个服务资源,参与到整个分布式事务中,然后主业务服务在第一阶段中分别调用所有的TCC服务的Try方法,最后根据第一个阶段的执行情况来决定对第二阶段的Confirm或者Cancel,流程图如下:

结合上图,我们举一个理财相关的例子,会更好理解一点:

①在账户服务中,对用户账户的余额进行扣减

②在产品服务中,对指定的产品进行申购,然后进行扣减

上面的①②分别对应不同的微服和数据库,在TCC中,要针对账户和产品服务分别提供Try、Comfirm和Cancel,逻辑如下

1、在账户服务的Try方法中对实际申购金额进行冻结(排除金额冲突),Confirm方法把Try冻结的资金进行实际的扣减,Cacel把Try冻结的资金进行解冻

2、理财产品服务的Try中将本次申购的部分额度进行冻结,Confirm方法把Try方法中冻结的额度进行实际扣减,Cacel方法把Try中冻结的额度进行释放

在上述的逻辑中,一个主业务方法中,分别调用这两个服务对外提供的处理方法(也就是资金扣减和可申购额度的扣减),在做处理过程时,会先调用Try来做资源预留,如果这两个方法处理都正常,TCC事务协调器就会调用Confirm对预留资源进行实际处理,否则TCC事务协调器发现Try中有异常失败,就会调用各个服务的Cancel进行回滚,从而保证数据的一致性

但有些特殊情况:如果有些服务挂掉了,导致没有收到TCC事务协调器的Calcen或者Confirm请求,就会出现数据不一致的问题,那咋办嘞,其实TCC事务框架会记录一些分布式事务的操作日志,保存是分布式事务运行的各个阶段和状态,TCC事务会通过操作日志来进行retry,以此达到数据的最终一致性,而且TCC服务支持接口调用失败发起重试,所以TCC的接口都需要满足幂等性

2、基于可靠性消息的最终一致性方案

这是互联网公司比较常用的分布式数据一致性解决方案,他利用的消息中间件的可靠性机制来实现数据一致性的投递

举个栗子:

在电商的支付中,用户完成订单的支付后,不用等待支付结果,这个时候对于系统来说,多数是在发起支付之后,等到第三方支付平台提供一部支付结果通知,再根据结果来重置订单的支付状态,如果是支付成功,现在很多金融企业都会有积分体系,这个时候给用户增加一定的积分、优惠卷啥的,所以,当系统接收到第三方返回的支付结果时,需要更新支付服务的支付状态,以及更新账户服务的积分余额,一个状态一个更新积分,这就是数据一致性问题,上面这个场景其实不是实时的,而且不要求是实时的,所以我们可以采取基于可靠性消息的最终一致性方案来保证支付服务和账户服务的数据一致性,看一下图结合理解一下:

支付服务受到支付结果通知后,先更新支付订单的状态,在发送一条消息到分布式消息队列中,账户服务会监听到指定队列的消息并进行相应的处理,完整数据的最终一致

但是,也是有点问题的,就是支付的本地事务与发送消息这个操作的原子性问题:

  • 先发送消息,在执行数据库事务,这种情况下可能会出现消息发送成功但是本地事务更新失败的问题,会导致数据不一致的问题
  • 先执行数据库事务操作,在发送消息,在这种情况下可能会出现MQ响应超时导致服务异常,从而将本地事务回滚,但是消息可能已经发送成功了,这种情况也会导致数据不一致的问题

那该咋解决嘞,其实前人已经种好树了,我们直接乘凉就行了,以RocketMQ来说,他提供了事务消息模型,我们看一下官方的流程图

具体执行流程是:

  • 生产者发送一个事务消息到队列上,队列只记录这条消息的数据,此时消费者无法消费这条信息
  • 生产者执行具体的业务逻辑,完成本地事务的操作
  • 接着生产者根据本地事务的执行结果发送一条确认消息给队列服务器,如果本地事务执行成功,则发送一个commit消息,标识在第一部中发送的消息可以被消费,否则队列服务器会把第一步存储的消息删除掉
  • 如果生产者在执行本地事务的过程中因为某些情况一直没有给队列服务器发送确认指令,那么队列服务器会定时主动回查生产者获取本地事务的执行结果,然后根据回查结果来决定这条消息是否需要投递给消费者
  • 队列服务器上存储的消息被生产者确认之后,消费者就可以消费这条消息了,消息消费之后会发哦是那个一个确认标识给队列服务器,标识消息投递成功

在RocketMQ事务模型中,事务是生产者来完成的,消费者无需关心,因为队列可靠性投递机制的存在,如果消费者没有接收到该消息,那么消息队列服务器会重复投递的,从而实现生产者的本地数据和消费者的本地数据在消息队列的机制之下达到最终一致

RocketMQ中最核心的机制就是事务回查,变被动为主动,你不告诉我执行结果,我定期来问,就是这么个意思

3、最大努力通知型 

基本和上面说到的基于可靠性消息最终一致性方案是一致的,比较适用于对数据一致性要求不太高的场景,最典型的使用场景是支付宝里面的支付结果通知,看图剖析:

讲解一下流程,来了解最大努力通知型的处理过程:

  • 用户先创建一个支付订单,然后调用支付宝的支付功能发起支付
  • 跳转到支付页面完成付款,支付宝也会针对用户创建一个支付交易,并且根据用户的支付结果记录用户的支付状态
  • 支付完成后会有一个回调通知给用户,用户收到该回调之后,根据结果修改本地支付订单的状态,并且返回一个支付状态给支付宝
  • 针对这个订单,正常情况下订单肯定是支付和通知都是成功的,但是如果出现网络问题等问题,导致一直不是成功的,那么最大努力通知型这里就用上了,如果用户一直没收到成功状态,那么回调会激活重试机制,不断叠加重试时间和次数,如果达到最大通知次数,还是没有返回成功的话,这个时候,就需要人工对账或者通过定时器去查询订单的交易结果来更新用户的订单状态

其实很简单,通过上面的案例,说明了最大努力通知,就是用户端如果一直没有收到成功时,支付宝会不断的进行重试,直到成功或者达到最大重试次数为止,通过重试机制来保证数据一致性的成功率

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 在高并发场景下,分布式事务是必须的。在选择分布式事务时,需要考虑以下几个方面: 1. 数据一致性:分布式事务需要保证不同节点之间的数据一致性,因此需要选择一种能够保证数据一致性的分布式事务方案,如 2PC(两阶段提交协议)或 3PC(三阶段提交协议)、TCC(补偿事务)等。 2. 性能:分布式事务需要涉及到多个节点之间的通信和协调,因此需要选择一种性能较好的分布式事务方案,如基于消息队列分布式事务、异步事务等。 3. 可扩展性:在分布式系统中,需要考虑系统的可扩展性,因此需要选择一种能够支持水平扩展的分布式事务方案,如基于分库分表的分布式事务。 4. 容错性:在分布式系统中,需要考虑节点故障的情况,因此需要选择一种能够保证容错性的分布式事务方案,如基于 Paxos 或 Raft 算法的分布式事务。 综上所述,分布式事务的选择需要综合考虑以上几个方面,选择一种适合自己业务场景的分布式事务方案,以保证系统的稳定性和可靠性。 ### 回答2: 在高并发场景下,分布式事务的选择是非常重要的。高并发场景通常由大量的用户请求和复杂的业务逻辑组成,需要保证系统的稳定性和数据的一致性。以下是几种常见分布式事务选择: 1. 两阶段提交(2PC):这是一种经典的分布式事务协议,它通过协调者和参与者之间的消息进行事务的提交,保证分布式系统中所有节点的一致性。然而,2PC存在单点故障和阻塞问题,同时在网络不稳定的情况下可能导致长时间的等待,不适合高并发场景的使用。 2. TCC(Try-Confirm-Cancel):TCC是一种基于补偿的分布式事务解决方案,它将事务拆分为三个阶段(试验、确认、取消)。在高并发场景下,TCC通过使用乐观锁或幂等性操作来解决并发冲突的问题,提供较好的性能和可伸缩性。 3. 本地消息表:在高并发场景下,将分布式事务转变为本地事务,使用本地消息表来实现事务的异步化和解耦。通过将事务操作记录插入本地消息表,并使用消息队列来异步处理事务,可以提高系统的吞吐量和并发处理能力。 4. Saga模式:Saga模式是一种面向分布式事务的异步解决方案,它将复杂的分布式事务拆分为一系列的局部事务。每个局部事务通过记录其提交和补偿操作,以保证系统的一致性。在高并发场景下,Saga模式具有较好的性能和可伸缩性,但需要更多的系统设计和开发工作。 综上所述,在高并发场景下,选择适合的分布式事务解决方案是非常重要的。根据具体的业务需求和系统特点,我们可以选择2PC、TCC、本地消息表或Saga模式等解决方案,来保证系统的稳定性和数据的一致性。最终的选择应该综合考虑系统性能、可伸缩性和开发成本等因素。 ### 回答3: 高并发场景下的分布式事务选择是一个比较复杂的问题,需要综合考虑系统的性能、一致性和可靠性等多个因素。 在高并发场景下,传统的单机事务往往无法满足要求,因此需要采用分布式事务来处理大量并发请求。目前主流的分布式事务解决方案有两种:基于两阶段提交(2PC)协议和基于消息队列的异步处理。 基于2PC协议的分布式事务是传统的解决方案,通过事务协调者协调各个参与者的事务操作,实现分布式事务的一致性。但是2PC存在的问题是性能低下和可靠性不高。2PC协议需要进行同步的预提交、提交和回滚等操作,整个流程需要等待所有参与者的响应,这会导致事务的响应时间长,并发能力受到限制。同时,2PC的串行执行也对系统的可靠性提出了较高要求,一旦协调者宕机,整个事务将无法进行。 基于消息队列的异步处理是一种新的解决方案,它将事务操作封装为消息,通过消息队列来进行异步处理。参与者将事务消息发送至消息队列,由消息队列异步处理消息,保证事务的可靠性和一致性。通过将事务操作异步化,可以大大提高系统的并发能力和性能。而且,基于消息队列解决方案对系统的可靠性要求较低,即使消息队列宕机,事务消息也可以通过存储进行恢复。 综上所述,在高并发场景下,基于消息队列的异步处理是更好的分布式事务选择。它能够提供较好的性能和可靠性,适应大规模并发的需求。但需要注意的是,选择分布式事务方案时需要根据实际需求综合考量各种因素,目前还有其他的解决方案,如基于补偿事务和Saga模式等,可以根据具体情况进行选择。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值