分布式事务及相应解决方案的一点理解

事务

首先,先理解一下什么是事务:提供一种机制将一个活动涉及的所有操作纳入到一个不可分割的执行单元,组成事务的所有操作只有在所有操作均能正常执行的情况下方能提交,只要其中任一操作执行失败,都将导致整个事务的回滚。简称:All or Nothing

数据库事务

数据库事务四大特性ACID;

  • A 原子性(Atomicity) All or Nothing。
  • C一致性(Consistency)在一个事务执行之前和执行之后数据库都必须处于一致性状态。如果事务中出现错误,将系统中的所有变化回滚
  • I 隔离性(Isolation)指的是在并发环境中,当不同的事务同时操纵相同的数据时,每个事务都有各自的完整数据空间。
  • D持久性(Durability)指的是只要事务成功结束,它对数据库所做的更新就必须永久保存下来。

分布式事务

分布式事务用于在复杂的分布式系统中保证不同节点(多数据库)之间的数据一致性
CAP理论

  1. Consistency 一致性 ,同一数据的多个副本是否实时相同。(all nodes see the same data at the same time)
  2. Availability 可用性,一定时间内 & 系统返回一个明确的结果 则称为该系统可用。(Reads and writes always succeed)
  3. Partition tolerance 分区容错性
    将同一服务分布在多个系统中,从而保证某一个系统宕机,仍然有其他系统提供相同的服务。

在分布式系统中,C、A、P三者不可兼得,只能同时满足两个。具体选择要依据业务场景,比如,在互联网项目中,集群规模越来越大,节点只会越来越多,所以节点故障、网络故障是常态,因此分区容错性也就成为了一个分布式系统必然要面对的问题。那么就只能在C和A之间进行取舍。而在类似银行的项目中,需要对于数据保持强一致性,可以在A和P之间做取舍。

BASE理论
CAP理论告诉我们在大多数业务系统中,往往会在一定程度上牺牲数据一致性,换取系统的可用性和分区容错性,而所谓的“一定程度上牺牲数据一致性”,并不是完全放弃数据一致性,而是牺牲强一致性,来换取弱一致性,也就是最终一致性。base可以理解为对于CAP理论的一种补充

  1. 基本可用(Basic Available),指分布式系统在出现不可预知故障的时候,允许损失部分可用性
  2. 软状态(Soft state),允许系统中的数据存在中间状态,并认为该状态不影响系统的整体可用性,即允许系统在多个不同节点的数据副本存在数据延时。
  3. 最终一致性(Eventual Consisstency),同一数据的不同副本的状态,可以不需要实时一致,但一定要保证经过一定时间后仍然是一致的。

分布式事务解决方案:

XA Transactions(2PC)

在这里插入图片描述
二阶段提交,将事务的提交过程分隔成两个阶段。

  1. 准备阶段,准备阶段,每个资源管理器(事务参与者)都会被轮训一遍,事务管理器(事务管理者)给每个资源管理器发送Prepare消息,每个资源管理器要么直接返回失败(如权限验证失败)或异常,要么在本地执行事务等等,但不Commoit,处于Ready状态。
  2. 提交阶段,如果事务管理器(事务管理者)收到了资源管理器(事务参与者)的失败信息(如异常、超时等),直接给每个资源管理器发送回滚(Rollback)消息;否则,发送提交(Commit)消息;资源管理器根据事务管理器的指令执行Commit或者Rollback操作,释放所有事务处理过程中使用的锁资源。(注意:必须在最后阶段释放锁资源)

从二阶段提交的工作方式看,其优点是:尽量保证了数据的强一致提交事务的过程中,需要多个节点之间进行协调,各节点对锁资源的释放必须等到事务最终提交。这处理,必然会增加执行事务的时间,也就意味着对于锁资源的长时间占有,当事务并发量达到一定程度时,会严重影响系统的性能。不仅如此,二阶段提交还会有一些缺点

  1. 同步阻塞问题。执行过程中,所有参与节点都是事务阻塞型的。当参与者占有公共资源时,其他第三方节点访问公共资源不得不处于阻塞状态。
  2. 单点故障。由于协调者的重要性,一旦协调者发生故障。参与者会一直阻塞下去。尤其在第二阶段,协调者发生故障,那么所有的参与者还都处于锁定事务资源的状态中,而无法继续完成事务操作。(如果是协调者挂掉,可以重新选举一个协调者,但是无法解决因为协调者宕机导致的参与者处于阻塞状态的问题)。
  3. 数据不一致。在二阶段提交的阶段二中,当协调者向参与者发送commit请求之后,发生了局部网络异常或者在发送commit请求过程中协调者发生了故障,这回导致只有一部分参与者接受到了commit请求。而在这部分参与者接到commit请求之后就会执行commit操作。但是其他部分未接到commit请求的机器则无法执行事务提交。于是整个分布式系统便出现了数据部一致性的现象。
  4. 无法解决的问题,协调者在发出commit消息之后宕机,而唯一接收到这条消息的参与者同时也宕机了。那么即使协调者通过选举协议产生了新的协调者,这条事务的状态也是不确定的,没人知道事务是否被已经提交。

TCC

TCC 其实就是采用的事务补偿机制,其核心思想是:针对每个操作,都要注册一个与其对应的确认和补偿(撤销)操作。它分为三个阶段:

  1. Try 阶段主要是对业务系统做检测及资源预留。
  2. Confirm 阶段主要是对业务系统做确认提交,Try阶段执行成功并开始执行 Confirm阶段时,默认 Confirm阶段是不会出错的。即:只要Try成功,Confirm一定成功。
  3. Cancel 阶段主要是在业务执行错误,需要回滚的状态下执行的业务取消,预留资源释放。

这种通过人为的方式实现了两段提交事务,虽然流程相对简单,但是不同的业务场景所写的代码都不一样,复杂度也不一样,因此,这种模式并不能很好地被复用。

本地消息表

在这里插入图片描述
本地消息表方案,其核心思想是将分布式事务拆分成本地事务进行处理。
大致思路如下:
消息生产方,需要额外建一个消息表,并记录消息发送状态。消息表和业务数据要在一个事务里提交,也就是说他们要在一个数据库里面。然后消息会经过MQ发送到消息的消费方。如果消息发送失败,会进行重试发送。

消息消费方,需要处理这个消息,并完成自己的业务逻辑。此时如果本地事务处理成功,表明已经处理成功了,如果处理失败,那么就会重试执行。如果是业务上面的失败,可以给生产方发送一个业务补偿消息,通知生产方进行回滚等操作。

生产方和消费方定时扫描本地消息表,把还没处理完成的消息或者失败的消息再发送一遍。
虽然实现了最终一致性,但是消息表会耦合到业务系统中。

消息中间件(消息事务)

基于消息中间件的两阶段提交,本质上是对消息中间件的一种特殊利用,它是将本地事务和发消息放在了一个分布式事务里,保证要么本地操作成功成功并且对外发消息成功,要么两者都失败。
在这里插入图片描述
基于消息中间件的两阶段提交往往用在高并发场景下,将一个分布式事务拆成一个消息事务(A系统的本地操作+发消息)+B系统的本地操作,其中B系统的操作由消息驱动,只要消息事务成功,那么A操作一定成功,消息也一定发出来了,这时候B会收到消息去执行本地操作,如果本地操作失败,消息会重投,直到B操作成功,这样就变相地实现了A与B的分布式事务。虽然能够完成A和B的操作,但是A和B并不是严格一致的,而是最终一致的,我们在这里牺牲了一致性,换来了性能的大幅度提升。当然,这种玩法也是有风险的,如果B一直执行不成功,那么一致性会被破坏。

总结:

分布式事务,本质上是对多个数据库的事务进行统一控制,可以分为:不控制、部分控制和完全控制。不控制就是不引入分布式事务,部分控制就是各种变化的两阶段提交,包括消息事务、TCC模式,而完全控制就是完全实现两阶段提交。部分控制的好处是并发量和性能很好,缺点是数据一致性减弱了,完全控制则是牺牲了性能,保障了一致性,具体用哪种方式,最终还是取决于业务场景。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值