分布式事务之理论基础

分布式事务的概念理论

事务


具备以下四个基本特性(ACID)

  • 原子性(Atomicity):一系列操作作被看作一个整体,要么全部成功,要么全部失败

  • 一致性(consistency):如果把所有参与者的数据看成是一个数据集,那么操作前后,数据的总量是不增不减的。也可以理解成数据是满足完整约束的。举例:一个数据集中只有两个参与者A&B,A持有100元,B持有0元,总额100元;A对B转账50元,余额50,B收到50,余额50,金额总量仍然是100,这就是一致性

  • 隔离性(Isolation):事务内部的数据对其它事务是不可见的,这也是对原子性的补充。原子性把系列操作看作一个操作,那么内部操作是不可见的

  • 持久性(Durability):一个事务完成之后数据被永远保存下来,其它操作和故障都不会对事务的结果产生影响

分布式事务


分布式事务是指事务的参与者,支持事务的服务器,资源服务器以及事务管理器分别位于不同的系统之中

也就是说,需要在不同的数据库之间实现事务

带来的挑战:

  1. 多个子系统独立,那么多个子系统所构成的大系统,导致了大系统的管理者也就是事务协调器外置,增加了一致性的难度

  2. 网络的不稳定性

一致性的划分


  • 强一致性:任何一次读都能都到最新的数据,系统中的所有参与者,看到的操作顺序,都和全局时钟下的顺序一致。简而言之,在任意时刻,所有节点中的数据是一致的

  • 弱一致性:数据更新后,如果能容忍后续的访问只能访问到部分或者全部访问不到,则是弱一致性

  • 最终一致性:不保证在任意时刻任意节点上的同一份数据都是相同的,但是随着事件的迁移,不同节点上的同一份数据总是在向趋同的方向变化。简单说,就是在一段时间后,节点间的数据会最终达到一致性

弱一致性和最终一致性比较容易混淆,比较下区别:

弱一致性,指的是数据更新后,其它参与者并不会马上访问到,访问到的是历史数据,但是从访问的时间线来看,每次访问到的结果都是顺序的,所以也叫顺序一致性

最终一致性,指的是在一定的时间之后,访问到的结果是一样的,假如中间经过了N次操作,但是可能先访问到了之后的操作结果,然后再访问到之前的操作,但是经过一定的时间之后,访问到的数据是最新的

从这点来看,InnoDB实现的可重复读隔离级别就是弱一致性,通过MVCC实现快照读,读取到的不是最新数据,而是历史的某个快照

Zookeeper实现的zab协议,因为允许半数节点成功则提交,那么连接点失败节点的客户端读取到的也是历史数据,所以也叫顺序一致性

CAP原则


CAP分别指 Consistency(一致性),Avaliabity(可用性),Partition tolerance(分区容错性)

CAP原则的内容是:在一个分布式系统中,CAP不能同时满足

另外,这里的一致性指的是,在分布式系统中的所有数据备份,在同一时刻是否相同,也就是强一致性

CAP中,主要是C和A不能同时满足,即不能满足强一致性的情况下,还能满足可用性

证明CA不能同时满足

数据同步过程中,出现了网络无法访问,或者宕机的情况

此时只有两种方式: 要么阻塞等待网络或服务恢复之后,再同步,保证一致性

要么允许客户端访问到历史数据,保证可用性

BASE理论


BASE理论指的是基本可用Basically Avaliable,软状态Soft Stat,最终一致性

核心思想是即便无法做到强一致,但应该采用适合业务场景的方式保证最终一致性

比如:银行转账,A向B发起转账100元,系统首先冻结A账户100元,等待B成功收到100元之后,再将冻结金额扣除

银行转账的双方,都能接受数据的延迟,这就是适合业务场景的方式

分布式事务解决方案的理论模型

XA协议包含:

  • 两阶段提交2PC
  • 三阶段提交3PC

3PC在2PC的基础上增加了一个询问阶段和超时机制,避免资源被永久锁定,但仍然存在宕机的问题,导致数据不一致,因此3PC所做的工作有点多余

两阶段XA


2PC的执行分为两个步骤:

  1. Prepare:事务管理器向所有本地资源管理器发起请求,询问是否是ready状态,所有事务都将事务能否成功的信息反馈给协调者,锁住对应的资源

  2. Commit:事务管理器根据所有本地资源管理器的反馈,通知所有本地资源管理器,步调一致地在所有分支上提交或回滚

因此实现XA需要有3个接口,注意,这是在数据库层面的commit,rollBack

1.prepare接口,锁定资源

2.commit接口,提交事务

3.rollBack接口,回滚事务

存在的问题:

1.prepare锁住对用的资源,整个过程时阻塞的

2.事务协调者发生宕机,导致事务不一致

TCC


TCC理论上也是XA协议的一种实现,区别只是讲数据库层的XA提升到了service层

三个角色:事务协调者,事务发起者,事务参与者

TCC需要在Service层实现三个接口

  1. Try阶段,锁定对应的资源

  2. Confirm阶段,确认,提交资源

  3. Cancel阶段,取消,释放资源

XA总结


无论2PC,3PC还是TCC的理论模型可以看到,都无法完全保证事务的一致性

所以实际的上解决方案是XA的变种,但还是基于XA的

实际方案:

  • 在事务协调者中维护一个大事务表,记录状态

  • 在事务协调者中维护一个小事务表,记录每个事务参与者的状态

  • 事务协调者通过过定时检查大事务,然后再找到小事务对应的参与者,通过调用XA两阶段的两阶段接口进行补偿,达到最终一致

    所以,这也要求两阶段接口具有幂等性

本地消息表


本地消息表方案最初由ebay架构师提出,该方案中涉及消息生产者和消息消费者两个角色

本地消息表.jpg

步骤:

1.A业务事务完成时,写入一条消息到本地消息表,记录消息状态是否被成功处理,使用本地事务保证数据一致性,并发送数据到MQ,如果发送MQ失败,则使用定时任务扫描补偿

2.B业务消费MQ,并保证消费的幂等性,如果消费成功,则通知A业务更新消息表状态(可以是回调,也可以是MQ)

3.A业务根据通知消息更新消息状态

分析:

比较适合的场景是下单成功后,短信的发送,邮件的发送

如果是优惠券的发放,可能会出现优惠券不足,则可能会扣减失败,如果使用这种方式,则需要A业务设置一个中间状态,并支持回滚

尽最大努力通知


支付回调就是典型的尽最大努力通知的场景

第三方支付服务,如微信,支付宝,当处理完这笔订单之后,就会发起一个回调通知调用方

如果失败会继续重试,直到达到重试最大次数,然后交由对账系统来处理

分布式事务理论模型总结

从上面的分析可以看到,不同解决方案的理论模型适合不同的业务场景

主要参考:https://xiaomi-info.github.io/2020/01/02/distributed-transaction/

你可能感兴趣的:(分布式事务之理论基础)