vlambda博客
学习文章列表

浅谈分布式事务之解决方案篇


点击蓝字
关注我们


引言
浅谈分布式事务之解决方案篇
浅谈分布式事务之解决方案篇

什么是事务?举个生活中的例子:我们去淘宝买东西,“银行扣款成功和成功生成订单”就是一个事务的例子,银行扣款和生成订单必须全部成功,事务才算成功,任一个活动失败,事务将撤销所有已经成功的活动。事务可以看做是一个大的活动集合,它由不同的小活动组成,这些活动要么全部成功,要么全部失败。在传统的事务理论中,一个整体事务通常被称为全局事务(GlobalTx),而整体事务中的每个小活动单位则被称作事务分支(TxBranch)。全局事务的协调通常由专门的事务中间件负责完成,如Tuxedo、CICS、J2EE产品中的TX模块等。TxBranch的事务保证则通常由与之对应的资源管理器(ResourceManager,如DB、MQ等)负责完成,与之对应的是RM层的本地事务(LocalTx)。

浅谈分布式事务之解决方案篇
浅谈分布式事务之解决方案篇
一、基本概念
浅谈分布式事务之解决方案篇
浅谈分布式事务之解决方案篇

a)本地事务

本地事务即RM事务,应用程序通过RM提供的接口进行资源操作,如增删改类的SQL执行、消息的发送接收等,同时通过RM的事务接口控制事务的提交或回滚,所有操作的本地事务保证均由RM负责完成。本地事务的四大特性ACID如下:

A(Atomic):原子性,构成事务的所有操作,要么都执行完成,要么全部不执行,不可能出现部分成功部分失败的情况。

C(Consistency):一致性,在事务执行前后,RM数据的一致性约束没有被破坏。

I(Isolation):隔离性,RM中的事务一般都是并发的,隔离性是指并发的两个事务的执行互不干扰,一个事务不能看到另一个事务运行过程的中间状态。通过配置事务隔离级别可以避脏读、重复读等问题。

D(Durability):持久性,事务完成之后,该事务对数据的更改会被持久化到RM,且不会被回滚。


 b)分布式事务

随着分布式应用、微服务的发展,为了解决多服务、多应用间的事务一致性问题,在传统事务的基础上又衍生出分布式事务的概念。那么什么是分布式事务?分布式系统通常会把一个单体应用系统拆分为可独立部署的多个应用或服务,因此需要服务与服务之间远程协作才能完成事务操作,这种分布式环境下由不同的服务之间通过网络远程协作完成事务称之为分布式事务,例如用户注册送积分事务、创建订单减库存事务,银行转账事务等都是分布式事务。在分布式事务场景下,有下列两个非常重要的理论:


  • CAP理论

CAP理论涉及事务的三个维度:Consistency(一致性)Availability(可用性)PartitionTolerance(分区容忍性)。CAP理论告诉我们一个分布式系统最多只能同时满足一致性、可用性、分区容忍性三项中的两项。


浅谈分布式事务之解决方案篇


其中AP在实际应用中较多,AP即舍弃一致性,保证可用性和分区容忍性,但是在实际生产中很多场景都要实现一致性,比如主数据库向从数据库同步数据,即使暂时舍弃一致性,但是最终也需要数据同步成功来保证数据一致,这种一致性和CAP中的一致性不同,CAP中的一致性要求在任何时间查询每个节点数据都必须一致,它强调的是强一致性,但是最终一致性是允许可以在一段时间内每个节点的数据不一致,但是经过一段时间每个节点的数据必须一致,它强调的是最终数据的一致性。


  • Base理论

BASE 是指基本可用(Basically Available)软状态(Soft State)最终一致性(Eventually Consistent)三个短语的缩写。BASE理论是对CAP中AP的一个扩展,通过牺牲强一致性来获得可用性。当系统出现故障时,允许部分功能不可用但要保证核心功能可用性;允许数据在一段时间内是不一致的,但最终要达到一致的状态。满足BASE理论的事务,我们称之为“柔性事务”。

基本可用:分布式系统在出现故障时,允许损失部分功能的可用性,保证核心功能可用。如电商网站交易付款出现问题了,商品依然可以正常浏览。

软状态:由于不要求强一致性,所以BASE允许系统中存在中间状态(也叫软状态),这个状态不影响系统可用性,如订单的"支付中"、“数据同步中”等状态,待数据最终一致后状态改为“成功”状态。

最终一致:最终一致是指经过一段时间后,所有节点数据最终达到一致状态。如订单的"支付中"状态,最终会变为“支付成功”或者"支付失败",使订单状态与实际交易结果达成一致,但会存在一定时间的延迟。

浅谈分布式事务之解决方案篇
浅谈分布式事务之解决方案篇
二、分布式事务解决方案
浅谈分布式事务之解决方案篇
浅谈分布式事务之解决方案篇

为解决分布式事务问题,各种的分布式事务框架、开源事务中间件纷至沓来。这些解决方案有的基于传统事务理论的两阶段提交,有的采用代码侵入式的TCC模式,有的则采用第三方组件(消息队列等)实现最终一致性。基于解决方案的实现模式,我们大体将它们分为如下几类。


a)2PC

2PC即两阶段提交协议,是将整个事务流程分为两个阶段,准备阶段(Preparephase)提交阶段(Commitphase)。整个事务的协调由事务管理器(TM)负责完成,各个事务分支独自完成自己对应的RM部分事务。事务提交时,TM负责通知各个事务分支参与者进行准备阶段投票,各参与者进行自身状态检查,同时将自身状态结果返回给TM。TM根据投票结果决定事务的提交或回滚,如果提交,TM先记录事务日志,同时通知各事务分支参与者进行事务提交,各参与者提交都成功后,TM清除事务日志,否则进行重试尝试。

还是以电商购物为例,银行扣款、订单生成这两个操作都不能孤立的存在,这两个操作必定以事务操作的形式存在,即电商不会无缘无故地生成订单,更不会无缘无故地进行银行扣款,这两个操作必须同时完成,要么都成功,要么都失败。扣款、订单生成任何一个操作失败,都会引起另一个操作的回滚,退款或订单取消。整个事务过程由事务管理器和参与者组成,营销系统充当事务发起者,并通过事务管理器协调全局事务,支付系统、订单系统则是事务参与者,负责支付操作、订单生成相关的本地事务。

在当前IT领域中,大部分数据管理类系统软件均支持2PC协议,如数据库类的Oracle、MySQL,消息队列类的IBMMQ、TonglinkQ等。2PC协议的执行过程分为如下两个阶段,即准备阶段、提交阶段。

准备阶段(Prepare phase):事务管理器给每个参与者发送Prepare消息,每个数据库参与者在本地执行事务,并写本地的Undo/Redo日志,此时事务没有提交。

提交阶段(commit phase):如果事务管理器收到了参与者的执行失败或者超时消息时,直接给每个参与者发送回滚(Rollback)消息;否则,发送提交(Commit)消息;参与者根据事务管理器的指令执行提交或者回滚操作,并释放事务处理过程中使用的锁资源。注意:必须在最后阶段释放锁资源。

下面两幅图分别对应2PC协议中事务成功、失败的两种情况。

1.成功

浅谈分布式事务之解决方案篇

2.失败

浅谈分布式事务之解决方案篇


b)TCC

TCC(Try-Confirm-Cancel)又称补偿事务。其核心思想是:"针对每个操作都要注册一个与其对应的确认和补偿",常见的TCC分布式事务框架有Hmily、ByteTCC、Seata等。整个TCC分为三个操作:


Try:主要是对业务系统做检测及资源预留。

Confirm:确认执行业务操作。

Cancel:取消执行业务操作。


TCC事务的处理流程与2PC两阶段提交类似,不过2PC通常都是在跨库的数据库层面,而TCC作用于应用服务层,需要通过业务逻辑来实现。TCC作为分布式事务框架,自然有自身的优势,当然也存在一些问题,如下:


TCC的优势

  • 可以针对不同的业务做特定的优化处理、提高吞吐量。

  • 相对灵活,开发人员如果很熟悉TCC的话,可以灵活控制整个事务单元。


TCC的问题

  • 对应用的侵入性非常强,逻辑的每个分支都需要实现try、confirm、cancel三个操作。

  • 现难度比较大,需要按照不同故障状态、故障原因实现不同的回滚策略。

  • 为了满足一致性的要求,confirm和cancel接口必须实现幂等。


下面两幅图分别对应2PC协议中事务成功、失败的两种情况。

1.成功

浅谈分布式事务之解决方案篇

2.失败

浅谈分布式事务之解决方案篇


c)消息最终一致性

可靠消息最终一致性方案是指事务发起方依靠消息系统(MQ等)、消息消费逻辑等实现事务的最终一致性,当事务发起方执行完成本地事务后并发出一条消息,消息系统和本地事务构成全局事务,即本地事务执行、消息发送到MQ必须同时成功事务才算成功。消息到达MQ后,由MQ保证消息消费者一定能够接收到消息,并正常执行与之对应的业务逻辑。如果消息消费失败,则需有对应的补偿机制作为失败事务的补偿,包括人工核定失败消息并补偿事务(回滚对应的本地事务或补偿执行消息对应的业务逻辑)。该方案是利用消息中间件辅助完成事务,如下图:


浅谈分布式事务之解决方案篇


事务发起方(消息生产方)将消息发给消息中间件,事务参与方从消息中间件接收消息,事务发起方和消息中间件之间,事务参与方(消息消费方)和消息中间件之间都是通过网络通信,由于网络通信的不确定性会导致分布式事务问题,因此可靠消息最终一致性方案在实施时需要解决以下几个问题:


本地事务与消息发送的原子性问题:

本地事务与消息发送的原子性问题即:事务发起方在本地事务执行成功后消息必须发出去,否则就丢弃消息。即实现本地事务和消息发送的原子性,要么都成功,要么都失败。


事务参与方接收消息的可靠性:

事务参与方必须能够从消息队列接收到消息,如果接收消息失败可以重复接收消息。


消息重复消费的问题:

由于网络问题的存在,若某一个消费节点超时但是消费成功,此时消息中间件会重复投递此消息,就导致了消息的重复消费。要解决消息重复消费的问题就要实现事务参与方的方法幂等性。

消费失败补偿:

一旦发生消息消费失败,消息可能会进入死信队列(消费者返回消费失败),也可能直接丢弃(消费异常,但返回消费者返回成功,导致消息丢弃)。对于进入死信的消息,需要具备查询、再消费的功能,以完成消息消费逻辑补偿。对于丢弃的消息,需要有健全的异常检测机制,以及时发现消费异常,并能及时对异常消费完成补偿。

浅谈分布式事务之解决方案篇
浅谈分布式事务之解决方案篇
总结
浅谈分布式事务之解决方案篇
浅谈分布式事务之解决方案篇

本文通过典型的事务场景逐步给大家解释了事务相关的概念及最近兴起的分布式事务,并对分布式事务相关的CAP理论、BASE理论作了简单介绍。事务理论由来已久,但事务相关的解决方案却随着应用技术的发展不停地在演变,因此作者也对当前的典型事务解决方案做了详细的介绍,并对各种方案的优劣做了简要对比,这些方案包括两阶段提交、事务补偿、消息最终一致性等。通过本文,读者可以大概了解事务的由来及场景,以及当前常见的事务解决方案,便于读者在后续涉及事务相关产品、方案选型时作为参考。

浅谈分布式事务之解决方案篇


浅谈分布式事务之解决方案篇








金融科技干货分享 

每周一篇成长快乐





我知道你在看