日常总结:分布式事务解决方案

目录

什么是分布式事务

为什么有分布式事务

CAP与BASE理论

CAP理论

一致性

BASE理论

分布式事务解决方案

二阶段提交 2PC

第一阶段:准备阶段

第二阶段:提交执行

二阶段提交的优点

二阶段提交的缺点

三阶段提交 3PC

阶段一

阶段二

阶段三

三阶段提交的优点

三阶段提交的缺点

事务补偿 TCC

TCC的优点

TCC的缺点

本地消息表

本地消息表的优点

本地消息表的缺点

MQ

优点

缺点

最大程度通知


刚逛超市回来,路上路过一家麻辣烫,吃的时候无聊,就刷手机看,看到群里有人问分布式事务的处理方案,于是,回来之后,我也总结一下(因为单身狗,所以一个人吃,所以才无聊,呜呜呜)

什么是分布式事务

ok,首先,我们要知道什么是分布式事务,事务我们都知道(不知道事务的去,自己去补习去)

分布式事务,也就很简单,意味着分布式的事务

分布式事务,指的就是参与事务的服务器、资源等,分别位于不同的节点上,一个操作由这些参与者共同完成,这些操作者的各自小操作,要么都成功,要么,都失败

为什么有分布式事务

我们知道了什么是分布式事务,那,为什么要有分布式事务呢?

为什么要有事务,我们都知道,已经烂大街的例子,转账,这边扣了那边得加

而在分布式环境下,也有相同的问题,线上为了保证稳定与高可用,我们不可能是单体架构的

所以,一定要有分布式事务这个东西

CAP与BASE理论

CAP理论

一致性C-Consistency,可用性A-Availability,分区容错性P-Partition tolerance

一致性C:在分布式系统中的所有数据备份,在同一个时刻,是否有相同的值?

可用性A:在分布式系统中,集群内某些节点发生故障后,集群对外整体是否还能正常响应用户请求?

分区容错性P:就算出现了单个组件的无法使用,操作能否完成?

在系统中,我们说CAP最多只能满足两个,很明显的,任何扩展都需要依赖于数据分区,因此,我们必须在一致性和可用性舍弃一个        

我们在实际开发中,一般都会采用可用性而放弃一致性

当然,所谓的放弃一致性,并非不管数据的正确性,而是放弃强一致性,得到弱一致性

一致性

一致性分为三种,强一致性、弱一致性、最终一致性

  • 强一致性:系统中某个数据被更新后,后续任何对该数据的读取操作,都将得到的是更新后的值,也可以称做原子一致性,说简单点,在任何时刻,所有节点的数据都是一样的;而如果一个集群要提供强一致性,只要一个节点数据发生变化,其他节点必须都同步完成才可以之后,整个集群才可以继续对外提供服务,这样一定会损耗可用性
  • 弱一致性:系统中某个数据被更新后,后续任何对该数据的读取操作,可能拿到更新后的值,也可能拿到更新前的值
  • 最终一致性:最终一致性不保证任何时刻拿到的同一份数据是相同的,但是随着时间的推移,不同节点的数据一定是朝着相同的方向变化,最终一段时间后,达到一致状态(目前我们的系统就采用的最终一致性)

BASE理论

BASE理论是对CAP的可用性和一致性的一种平衡,BASE理论的核心观点就是:无法做到强一致性,但,可以根据不同节点的特点,使用适当的方式让系统达到最终一致性

BA-Basic Available 基本可用、S-Soft State 柔性状态、E-Eventual Consisstency 最终一致性

  • BA:基本可用;在某些情况下,系统仍旧能够返回一个明确的结果,就属于基本可用
  • S:柔性状态;允许系统的数据存在中间状态,该中间状态的存在,不会影响系统的整体可用性
  • E:最终一致性:同一个数据的不同副本,可以不用实时一致,但,最终一定要是一致的

分布式事务解决方案

接下来我们来看分布式事务的解决方案

在现在的分布式架构中,每个节点都只会知道自己的操作结果,而不知道别人的操作结果,所以,为了保持事务的原子性与一致性,需要引入一个协调者来掌控所有的操作结果,来决定到底是继续,还是回退

二阶段提交 2PC

二阶段提交,就是将事务的提交过程分为两个阶段来处理,这两个阶段分别是准备阶段和提交阶段,而参与到的角色,就是事务的协调者与事务的参与者,所谓事务协调者,一般都是事务的发起者,而事务的参与者,就是事务的执行者,当然,事务的参与者本身也可以是事务的执行者

第一阶段:准备阶段

准备阶段,由事务的协调者来发起询问,或者说查询,来确认所有的参与者是否能够提交事务,注意,所有的参与者只是确认,并非提交

第二阶段:提交执行

提交执行阶段,这一段就是协调者通知所有参与者提交事务,当所有的参与者都回复了成功,意味着这个事务就完成了

如果任何一个参与者在第一阶段认为不可以提交事务,或者说,协调者去协调能否提交,在规定时间内没有得到响应,这个事务也会被回退

无论结果如何,在第二阶段,这个事务都会结束

二阶段提交的优点

二阶段提交的优点已经算很明显了,尽可能保证了数据的强一致性(当然,不是100%)

二阶段提交的缺点

有经验的人一下就能看到二阶段提交的缺点

  1. 性能问题:在执行的过程中,所有参与了事务的节点,都是阻塞类型的,当参与者占用了公共资源,其他访问公共资源的,不得不等待或阻塞
  2. 可靠性问题:为了防止参与者出问题,协调者需要给每一个参与者指定超时时间,超时后认为失败,而协调者如果发生故障,参与者就会一直阻塞下去,需要额外的容错手段
  3. 数据一致性问题:假设协调者在发出提交指令之后挂了,而接收这条指令的参与者也挂了,即使通过类似选举的手段选出了新的协调者,谁也不知道这个事务是不是被更改过
  4. 实现复杂:直接牺牲了可用性,对性能影响巨大,高并发场景不适合用,且实现也复杂

三阶段提交 3PC

三阶段提交是二阶段提交的改良版,对比于二阶段提交,三阶段提交有两个地方变更

  • 在协调者、参与者,都设置超时机制
  • 在一阶段和二阶段中间额外插入一个准备阶段,保证在最后提交之前各个参与节点的状态是一样的

也就是说,三阶段提交有三个阶段,确认可提交---准备提交---提交

阶段一

三阶段提交的阶段一和二阶段提交的阶段一是一样的

阶段二

将操作都写入事务,但是不提交

假设参与者超时,或者参与者告知无法提交,·协调者就执行事务中断

阶段三

进行最后的提交,在这一个阶段,就算参与者无法收到协调者的消息,参与者都会在超时之后,继续执行事务

三阶段提交的优点

对比二阶段提交,三阶段提交降低了阻塞范围,等待超时后,参与者或者协调者就会中断事务,而阶段三中,就算协调者出现问题,各个参与者也会正常执行事务

三阶段提交的缺点

三阶段提交,很明显也依然存在着数据不一致的问题,如果参与者收到了准备提交指令,等待提交指令,而这个时候协调者要求中断事务,协调者无法通知到参与者,参与者会自己提交事务,就会导致数据不一致

事务补偿 TCC

所谓补偿事务,是一种侵入业务的两阶段提交方式,应该是现在用的比较多的,我们的系统有一部分是这样的,想法就是,针对每个操作,都实现一个对应的确认和错误补偿操作
T,代表尝试,try

C,代表取消,cancel

C,代表确认,confirm

以下订单举例

锁定库存,尝试创建订单,这就是try

根据try阶段的执行结果,确认执行哪个C,两个C具有幂等性,如果执行失败,那就不断重试,直到成功

如果成功,那就确认,如果失败,那就取消

TCC保证的是最终一致性,以try的操作为核心,其他操作为辅助

当然,TCC这种,也有概率在两个C失败,必须由人工处理的情况

TCC的优点

TCC对比上面,有一些比较明显的优点

  • 性能:在性能上,对资源的锁粒度变小了,不会锁定所有资源
  • 一致性:因为两个C操作,保证数据的最终一致性
  • 可靠性:可以解决协调者单点故障的问题,由主要发起方控制所有活动

TCC的缺点

TCC的缺点也十分明显,它要侵入业务,根据具体的业务来实现对应操作,开发成本会上去

本地消息表

本地消息表的核心,就是把分布式事务拆分成不同的本地事务

参加的角色分为事务主动方和事务被动方,事务主动方在自己的本地额外建立一个消息表,并且记录消息的发送状态和执行状态,这张消息表和自己业务数据的变更,在一个事务提交,然后消息通过MQ发送给事务被动方,发送失败,那就重试

而事务被动方,需要处理自己接收到的消息,并依照消息,完成自己应该执行的逻辑,如果业务失败,可以给事务主动方发送一个补偿消息,通知事务主动方回退等

如果处理成功了,发送给事务主动方,事务主动方更新消息表的状态,并执行其他操作

当然,需要做一些可能出现的容错处理

  1. 如果事务主动方出错,因为在本地,可以直接回退
  2. 如果发送消息等出错,直接重试发送就好,直到发送成功,对方接收到
  3. 如果业务处理失败,可以发消息,进行对应回退操作
  4. 如果事务被动方已经消费了消息,事务主动方要回滚,需要发消息等操作,来进行回滚
  5. 主动方和被动方定期扫描自己的消息表,失败的进行对应处理

本地消息表的优点

消息数据的可靠性存在DB,对MQ的依赖比较少

(这儿有人说实现简单,不过我个人觉得,不是特别合适的说法)

本地消息表的缺点

缺点也很明显,与具体业务绑定耦合,并且消息表也需要占用DB的资源,也会受限DB的资源

MQ

所谓MQ,不是指的像普通使用MQ一样, 而是将本地消息表放在了MQ里,目前只有rocketmq支持

流程其实也和本地消息表有点类似,但并不是很相同

首先发送准备消息到MQ,发送成功后,执行本地事务,如果执行成功,那就提交,MQ会把消息下发到消费端,如果执行失败,那就回退,MQ将消息删除,消费端如果接受失败,那就一直重试

优点

数据独立存储,不占用DB的资源,也降低了业务与消息之间的耦合性

吞吐量大于本地消息表

缺点

一次消息发送,需要两次网络请求(消息,提交或回退消息)

需要实现对应的消息处理接口

最大程度通知

如同字面意思,最大程度上努力通知

事务发起主动方进行推送,并且,接收方也可以调用发起方,进行数据的核对,也就是说,双方可以互相调用


以上,是我了解的分布式事务解决方案,当然,实际上不止这些,不过,对于我听都没听过,或者完全不懂的,我也不乱整理乱分享

总之,分布式事务会提高整体系统的复杂度,并且一定程度上会影响性能,所以,在实际开发中,如果能避免使用分布式事务,还是尽量不要去用

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值