微服务入门到入土(09)-分布式事务

1. 分布式事务概述

1.1 本地事务

在计算机系统中,更多的是通过关系型数据库来控制事务,这是利用数据库本身的事务特性来实现的,因此叫数据库事务。由于应用主要靠关系数据库来控制事务,而数据库通常和应用在同一个服务器,所以基于关系型数据库的事务又被称为本地事务。

在分布式系统中,一个操作如果跨越多个服务或者多个数据库的话。本地事务是无法回滚其他服务或其他数据库的事务的。因此分布式事务就随之出现了。

1.2 分布式事务

当一个业务跨越多个服务或数据库的时候,我们要保证的是,这多个服务要么全部成功,要么全部失败,这就是分布式事务要实现的目标。
微服务入门到入土(09)-分布式事务_第1张图片

1.3 事务的ACID原则

微服务入门到入土(09)-分布式事务_第2张图片

2. 理论基础

2.1 CAP定理

  • Consistency(一致性)
  • Availability(可用性):
  • Partition tolerance(分区容错性)

在分布式系统中无法同时满足这三个指标,这个结论就叫做CAP定理。

Consistency(一致性)
用户访问分布式系统中的任意节点时,得到的数据必须一致。

微服务入门到入土(09)-分布式事务_第3张图片

Availability(可用性)
用户在访问集群中的任意健康节点,必须能得到响应,而不是超时或拒绝。
微服务入门到入土(09)-分布式事务_第4张图片
由上图可以看出node02的数据还未同步到node03,如果这时有请求到node03的话就会阻塞或拒绝,直到数据同步完成,这样的话满足了一致性,但是却不能满足可用性。如果我们直接将node03上未同步的旧数据返回个用户,或者返回默认数据的话,这样就满足了可用性,但是却不能满足一致性了。如果两者都要满足的话,那么node03会自己形成一个独立分区,将于其他两个节点失去联系,其他两个节点能同时满足可用性和一致性。

Partition tolerance(分区容错性)

  • 分区:因为网络故障或其他原因导致分布式系统中的部分节点与其他节点失去连接(不是宕机),形成独立分区。
  • 容错:在集群出现分区时,整个系统也要持续对外提供服务。
    微服务入门到入土(09)-分布式事务_第5张图片

CAP定理总结:
在分布式系统中,分区是不可避免要出现的,我们不能让系统在出现分区的时候无法对外提供服务。因此,分区容错性是必须要满足的。因此CAP定理的主要问题还是C和A无法同时满足。

如果要满足A(可用性),那么当某个节点数据还未完成同步的话,也必须能够快速响应而不是超时或拒绝,这时候返回的数据可能是同步前的数据或默认数据,数据的一致性就无法得到保障。
如果要满足C(一致性),那么当某个节点还未完成同步的话,就必须等待同步完成,才返回数据。在等待的过程中,可能会超时,因此就无法保证系统的可用性。

2.2 BASE理论

BASE理论是对CAP的一种解决思路,在A和C之间进行调和。

  • Basically Available(基本可用)
    分布式系统出现故障时,允许损失部分可用性,只保证核心可用
  • Soft State(软状态):在一定时间内,允许出现中间状态,比如临时的不一致状态(订单支付的支付中状态,数据同步的同步中状态)
  • Eventually Consistent(最终一致性):虽然无法保证强一致性,但是在软状态结束后,最终达到数据的一致性。
    在这里插入图片描述

3. 分布式事务解决方案

常见的分布式解决方案有2PC、TCC、可靠消息最终一致性、最大努力通知等。

3.1 两阶段提交(2PC)- 解决方案

  • 准备阶段(Prepare phase)
    事务管理器给每个参与者发送prepare消息,每个参与者在本地执行事务,并写入本地的Undo/Redo日志,此时事务还未提交。
    (Undo日志是记录修改前的数据,用于数据库回滚。Redo日志是记录修改后的数据,用于提交事务后写入数据文件)
  • 提交阶段(Commit phase)
    事务管理器给每个参与者发送提交或回滚事务的消息。参与者提交或回滚数据库,并释放事务处理过程中占用的锁资源。
    注意:必须在最后阶段释放锁资源。

举例:
张三和李四好久不见,老友约起聚餐,饭店老板要求先买单,才能出票。这时张三和李四分别抱怨近况不如意,囊中羞涩,都不愿意请客,这时只能AA。只有张三和李四都付款,老板才能出票安排就餐。

准备阶段:老板要求张三付款,张三付款。老板要求李四付款,李四付款。
提交阶段:老板出票,两人拿票纷纷落座就餐。

例子中形成了一个事务,若张三或李四其中一人拒绝付款,或钱不够,店老板都不会给出票,并且会把已收款退回。

3.1.1 Seata的XA模式 - 实现方式

XA规范是X/Open组织定义的分布式事务处理(DTP,Distributed Transaction Processing)标准,XA规范描述了全局的TM与局部的RM之间的接口,几乎所有主流的数据库都对XA规范提供了支持。
传统的XA模式只有TM、RM两种角色,如下图。而Seata的XA模式做了一些封装,多了一种TC角色,使系统更加的健壮。

Seata结构:
微服务入门到入土(09)-分布式事务_第6张图片

传统XA模式:
微服务入门到入土(09)-分布式事务_第7张图片
微服务入门到入土(09)-分布式事务_第8张图片

Seata的XA模式:
微服务入门到入土(09)-分布式事务_第9张图片

优点

  • 事务的强一致性,满足ACID原则。
  • 常用数据库都支持,实现简单,并且没有代码侵入

缺点

  • 因为一阶段需要锁定数据库资源,等待二阶段结束才释放,性能较差
  • 依赖关系型数据库实现事务

3.1.2 Seata的AT模式 - 实现方式

AT模式同样是分阶段提交的事务模型,不过弥补了XA模型中资源锁定周期过长的缺陷。

工作模型
微服务入门到入土(09)-分布式事务_第10张图片
举例:
微服务入门到入土(09)-分布式事务_第11张图片
微服务入门到入土(09)-分布式事务_第12张图片
AT模式脏写问题
简而言之,就是A事务回滚的时候,通过日志恢复数据前,数据已经被B事务修改了,这时候再恢复数据,就会导致B事务修改的数据被覆盖。问题出现的原型就是没有做好事务的隔离性。
微服务入门到入土(09)-分布式事务_第13张图片
AT模式的写隔离
为了解决脏写问题,Seata引入了全局锁的概念。A事务正在操作某行数据的时候,会获得全局锁。B事务想修改该数据的时候发现该数据被A锁着,这样就会等A事务完成后释放锁了,B事务才能接着操作。
微服务入门到入土(09)-分布式事务_第14张图片
上图的事务1和事务2都是由seata管理的,如果事务2不是由seata管理的呢,这时候该怎么避免脏写问题呢?其实seata在阶段一保存快照的时候会把更新前和更新后的数据都保存,在阶段二回滚的时候会比较数据和更新后的数据是否一致,一致的话就回滚,不一致就不会滚了,如下图。
微服务入门到入土(09)-分布式事务_第15张图片
优点

  • 一阶段完成直接提交事务,释放数据库资源,性能比较好
  • 利用全局锁实现读写隔离
  • 没有代码侵入,框架自动完成回滚和提交

缺点

  • 两阶段之间属于软状态,属于最终一致
  • 框架的快照功能会影响性能,但比XA模式要好很多
  • 有可能会出现无法回滚的现象

3.2 TCC - 解决方案

TCC模式与AT模式非常相似,每阶段都是独立事务,不同的是TCC通过人工编码来实现数据恢复,不需要加锁,性能比AT模式要好很多。需要实现三个方法:

  • Try:资源的检测和预留;
  • Confirm:完成资源操作业务;要求Try成功Confirm一定要能成功。
  • Cancel:预留资源释放,可以理解为try的反向操作。

举例
微服务入门到入土(09)-分布式事务_第16张图片

TCC模式的优点

  • 一阶段完成直接提交事务,释放数据库资源,性能好。
  • 相比AT模式,无需记录日志,无效全局锁,性能好。
  • 不依赖数据库事务,而是依赖补偿操作,可以用于非事务型数据库。

TCC模式的缺点

  • 代码侵入性强,需要人工编写try、confirm、cancel方法
  • 软状态,事务是最终一致性
  • 需要考虑confirm和cancel失败的情况,做好幂等处理

3.2.1 Seata的TCC模式-实现方式

工作模型
微服务入门到入土(09)-分布式事务_第17张图片
TCC模式的空回滚和业务悬挂
微服务入门到入土(09)-分布式事务_第18张图片
微服务入门到入土(09)-分布式事务_第19张图片
总而言之,空回滚就是未执行try就执行cancel了。业务悬挂就是执行完cancel后又执行try了。

微服务入门到入土(09)-分布式事务_第20张图片
微服务入门到入土(09)-分布式事务_第21张图片

3.3 可靠消息最终一致性 - 解决方案

基本原理
微服务入门到入土(09)-分布式事务_第22张图片

如何保证消息的可靠性

参考 微服务入门到入土(08)-消息队列RabbitMQ

3.4 最大努力通知 - 解决方案

最大努力通知,也是依靠消息队列来实现的。只不过不能保证消息一定能发出去或者说不能保证消息一定能被消费。但是消息的生产者必须提供一个查询接口,以供消息发不出去的时候,让消费者可以自主查询。
比如支付服务,App调用微信的支付功能的时候,微信未通知调用发是否支付成功,同时也提供了对账功能,供用户查询是否支付成功,这样用户就算没有收到支付成功的通知,也可以自己去查询。

一般用于对接第三方系统。
微服务入门到入土(09)-分布式事务_第23张图片

你可能感兴趣的:(微服务全家桶,java,微服务,架构)