分布式事务
既然说起分布式事务,那么什么是分布式事务呢?简单来说就是说传统的单体系统架构、单体数据库已经无法满足海量的用户需求,这个时候就需要对原有系统进行升级改造,对大规模的流量进行分解到不同的应用服务中,数据也分散在不同服务器的数据库中存储,这样的结果就是对于数据的增删改查操作就会变得更加复杂,尤其是难以保证数据的一致性,那么这也就是常说的分布式事务了。
分布式事务理论基础
说到分布式事务,那么就一定会想到分布式事务相关的两个理论知识,CAP理论、Base理论
CAP理论
什么是CAP理论?CAP理论,指的是在一个分布式系统中,Consistency(一致性)、Availability(可用性)、Partition Tolerance(分区容错性),不能同时成立。
一致性
在互联网领域中,不管是哪家企业,数据的存储往往都不会是单份的,那么一致性就是指用户对数据的更新操作在数据库的所有副本中要么都执行成功,要么都执行失败。也就是说一致性要求所有数据节点的副本数据的更新是原子性操作,所有数据节点的副本数据都是最新的,用户从任意的数据节点请求到的都是数据的最新状态。
可用性
可用性就是说用户请求数据的时候,可以快速的得到响应,虽然每个存储节点的数据可能会不一致,但是出于可用性状态的系统,任何事务的操作都可以得到响应的结果,不会存在超时或者响应错误的情况,只是存在返回的不是最新数据或者说返回旧数据的情况。
分区容错性
分区容错性就是说如果存储系统部署的只有一个节点,那么节点挂掉,整个系统将无服务可用。那么将存储系统部署在不同的节点上,并且这些节点处于不同的网络中,这样就形成了网络分区,此时,即使其中一个节点不能对外提供服务了,其他节点还可以正常服务,整个系统处于可用状态。
Base理论
BASE 理论是对 CAP 中的一致性和可用性进行一个权衡的结果,理论的核心思想就是:我们无法做到强一致,但每个应用都可以根据自身的业务特点,采用适当的方式来使系统达到最终一致性。
基本可用
基本可用就是说当系统发生故障时,允许损失系统的部分可用性,比如响应时间或者部分功能,但是要保证系统基本可用。比如在电商场景中,积分功能故障时,商品下单功能不受影响,或者下单功能故障,加购物车或浏览商品功能不受影响。
软状态
这个软状态就是说可以允许存在一个中间状态,比如支付中,而不是只有待支付、支付成功、支付失败的状态,这些中间状态不影响系统的整体可用性,知识允许系统各个节点之间存在延迟。
最终一致性
最终一致性就是说最后各个数据副本的状态达到一致,而不是要求各个数据副本状态值实时一致,比如支付中的状态,最后都会变成支付成功的最终状态。
分布式事务解决方案
基于分布式事务的理论基础,那么分布式事务的解决方案可以分为强一致性解决方案和最终一致性解决方案。
强一致性解决方案
什么是强一致性解决方案呢?顾名思义,就是说不管在任意时刻查询参与全局事务的各节点的数据,返回的数据都是一致的。
最常见的比如银行转账的场景,你不能说对方都收到钱了,你这边账户还没有扣款;或者说你这边都已经扣款了,但是对方迟迟没收到钱,这些都是双方不能容忍的,因而就必须用强一致性解决方案,保证应用程序在任何时间,任意节点的数据都是最新的。
强一致性最常见的两种模型:2PC模型、3PC模型
2PC模型
2PC模型的执行流程
Prepare阶段,TM会向每个参与全局事务的RM发送Prepare消息,RM要么返回失败,要么在本地执行相应的事务,同时将事务写入本地的Redo Log和Undo Log文件中,但是此时事务并没有提交。
Commit阶段,如果TM收到了参与全局事务的RM返回的失败消息,那么TM直接给Prepare阶段返回成功消息的RM发送回滚消息;反之,则给每个RM发送Commit消息,相应的RM根据TM发送过来的消息指令,执行对应事务的回滚或者提交操作,并且释放事务处理过程中使用的锁资源。
2PC存在的问题
同步阻塞:事务执行过程中,所有参与事务的节点都会对其占用的公共资源加锁,导致其他访问公共资源的线程或者进程阻塞。
单点故障:如果TM故障,则RM会一直阻塞。
数据不一致:如果Commit阶段部分RM没有接收到TM发送的Commit指令,会引起数据不一致。
3PC模型
3PC模型执行流程
3PC模型是把2PC模型的Prepare阶段分为两个阶段,同时引入了超时机制。
CanCommit阶段,TM向参与全局事务的RM发送CanCommit消息,RM收到消息 后认为能够执行事务,会向TM响应Yes消息,进入预备状态。
PreCommit阶段,TM向参与全局事务的RM发送PreCommit消息,RM收到消息后,执行事务操作,将Undo和Redo日志写入日志文件,并向TM响应Ack状态,但是此时不会提交事务,如果任何一个RM向TM反馈了No或者等待超时后,TM无法接收到所有参与者的反馈,那么就会中断事务,TM向所有参与者发送 abort 请求,或者响应超时自动中断事务。
doCommit阶段,如果TM收到了所有全局事务参与RM响应的Ack状态,则TM向参与全局事务的RM发送doCommit消息,RM接收到消息后正式提交事务,并释放执行事务期间占用的资源,同时向TM响应事务Ack消息,TM收到RM响应的事务已提交状态,完成事务提交。
3PC问题
与2PC模型相比,3PC一旦RM迟迟没有收到TM发送的commit请求,就会自动进行本地commit,这样相对有效地解决了TM单点故障的问题,减少了事务执行过程中的阻塞现象,但是如果RM无法及时收到TM发送的消息,那么RM就会执行提交事务操作,而不是一直处于占用资源阻塞状态,因而这种机制也会导致数据不一致问题。
最终一致性解决方案
最终一致性解决方案就是说并不要求参与事务的各个节点的数据时刻保持一致,而是允许有一个中间状态,在一段时间后,能够达到数据的最终一致状态就可以。
优点:性能比较高,适合高并发场景,具备可用性。
缺点:某一时刻查询到的数据可能会不一致,对于事务一致性要求高的场景不适用。
典型的最终一致性方案有:TCC解决方案;可靠消息最终一致解决方案;最大努力通知型解决方案。下面主要讲述一下TCC解决方案
TCC解决方案
TCC模式主要分为三个阶段:
1.Try阶段:完成所有业务的一致性检查及预留业务资源
2.Confirm阶段:此阶段会真正执行业务操作,不再进行业务检查,此阶段操作需要满足幂等性
3.Cancel阶段:取消执行业务操作,释放业务资源
TCC方案执行流程
流程图如下
在使用TCC解决方案时需要考虑到幂等问题,比如在服务器宕机或网络异常等情况时,为了保证方法正常执行,通常会加入超时重试机制,而一旦触发重试机制就有可能导致数据不一致,这时候就需要保证TCC方案的Confirm阶段和Cancel阶段的幂等性。
TCC方案举例
日常生活中不管是京东还是淘宝,大家总是都在线购物过吧,这也就是常说的电商业务场景了,电商业务场景中最有代表意义的场景就是支付订单场景,这个场景包括修改订单状态、扣减库存、增加积分、创建出库单、物流单等业务,那么这些业务要么全部执行成功,要么全部执行失败,必须是一个完整的事务整体。
那么问题来了,如果没有分布式事务,问题就来了:
1.【订单服务】修改订单状态成功,调用远程【库存服务】扣减库存异常,库存扣减失败,而【积分服务】【仓储服务】都执行成功,则此时就是修改订单状态成功,库存未扣减,可能超卖
2.【订单服务】修改订单状态失败,【库存服务】扣减库存成功,此时会出现库存异常扣减情况。
因此,为了保证数据最终一致性,对于订单服务,不能简单的将订单状态直接修改为‘支付成功’,将库存直接修改为‘已扣减’,而是应该有一个中间状态,因此对于支付订单场景,
Try阶段主要业务流程
1.【订单服务】修改订单状态为‘支付中’
2.【库存服务】冻结下单的库存数量,而不是直接扣减库存数量
3.【积分服务】不是直接增加积分,而是预增加积分
4.【仓储服务】不在直接生成出库单,而是将出库单标记为‘未知’
Try阶段整体流程图就是
Confirm阶段主要业务流程
1.【订单服务】修改订单状态为‘支付成功’
2.TCC分布式事务框架调用【库存服务】中Confirm阶段的方法真正扣减库存
3.TCC分布式事务框架调用【积分服务】中Confirm阶段的方法真正增加积分
4.TCC分布式事务框架调用【仓储服务】中Confirm阶段的方法将出库单的状态更新为‘已创建’
Confirm阶段流程图就是
Cancel阶段主要流程
1.【订单服务】修改订单状态为‘已取消’
2.TCC分布式事务框架调用【库存服务】中Cancel阶段的方法进行事务回滚
3.TCC分布式事务框架调用【积分服务】中Cancel阶段的方法进行事务回滚
4.TCC分布式事务框架调用【仓储服务】中Cancel阶段的方法进行事务回滚,同时将出库单的状态更新为‘已取消’
Cancel阶段流程图就是
这样整个TCC分布式解决方案的基本原理和流程图到这里就讲述完了,希望对大家有帮助。