互联网科技

快!别错过,想要深入理解分布式事务,看这篇就足矣!

2022-03-17  本文已影响0人  风平浪静如码

导读概述

随着业务的快速发展,业务复杂度越来越高,大部分互联网公司几乎都会从单体走向分布式,特别是转向微服务架构,随之而来就必然遇到分布事务这个难题。

本文主要介绍一下Seata是如何保证数据一致性的,将从以下几个方面介绍一下分布式实现方案

1、介绍一下分布式理论(此部分如果已经掌握了可以跳过,看下面部分分享)

2、什么是Seata

3、Seata AT模式下如何解决分布式事务,应用场景

4、Seata TCC模式下如何解决分布式事务、应用场景、变种场景使用

5、Seata 下的Saga模式

本文以下单占库存案例为主线分享Seata分布式解决方案。

分布式理论

什么是事务?

指的就是一个操作单元,在这个操作单元中的所有操作最终要保持一致的行为,要么所有操作都成功,要么所有的操作都被撤销。

使用事务目的是什么

说明白了就是保证数据的一致性。

什么是本地事务呢

我们常常指的是关系型数据库的事务,关系型数据库事务四大特性:

优点:可以保证单机数据库层面的数据一致性。

为什么要使用分布式事务

分布式事务在分布式环境下,为满足可用性、性能与降级服务的需要,降低一致性与隔离性的要求,一方面遵循 BASE 理论

同样的,分布式事务也部分遵循 ACID 规范:

需求是这样的

随着业务发展在微服务架构下,【订单服务】和【库存服务】在两个业务系统里,同时分别调用对应的订单DB和库存DB,要求保证:要么库存和订单下单一起成功,如果库存占用和订单下单有一方失败要么就要回滚,保证数据的一致性。

此时场景数据库级别的事务就有些捉襟见肘了,此时分布式事务就派上用场了。

分布式事务常见解决手段有哪些呢?

两阶段提交2PC、三阶段提交3PC、TCC、SAGA、本地消息表、基于可靠消息保证最终一致、最大努力通知等方案。

由于分布式事务方案,无法做到完全的ACID的保证,没有一种完美的方案,能够解决掉所有业务问题。因此在实际应用中,会根据业务的不同特性,选择最适合的分布式事务方案。

什么是分布式事务呢?

1、分布式事务:

2、常见使用场景

如用户注册送积分事务、创建订单减库存事务,银行转账事务等都可以应用分布式事务,分布式事务就是为了保证在分布式场景下,数据操作的正确执行。

提到分布式场景就绕不开CAP理论,三者只能满足两点,来解决分布式场景的问题,那么接下来先了解一下什么是CAP。

CAP原则

CAP 原则又称 CAP 定理,又被叫作布鲁尔定理,指的是在一个分布式系统中, Consistency(一致性)、 Availability(可用性)、Partition tolerance(分区容错性),三者不可得兼。

CAP 原则的精髓就是要么AP,要么CP,要么AC,但是不存在CAP。如果在某个分布式系统中数据无副本,那么系统必然满足强一致性条件,因为只有独一数据,不会出现数据不一致的情况,此时C和P两要素具备,但是如果系统发生了网络分区状况或者宕机,必然导致某些数据不可以访问,此时可用性条件就不能被满足,即在此情况下获得了CP系统,但是CAP不可同时满足。

即要保证数据一致还要保证可用,鱼和熊掌不可兼得,那么就要取舍,于是产生以下几种一致性策略。

强一致性、弱一致性、最终一致性

1.强一致性

任何一次读都能读到某个数据的最近一次写的数据。系统中的所有进程,看到的操作顺序,都和全局时钟下的顺序一致。简言之,在任意时刻,所有节点中的数据是一样的。如:2PC、3PC、XA都属于强一致性方案。

2.弱一致性

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

3.最终一致性 不保证在任意时刻任意节点上的同一份数据都是相同的,但是随着时间的迁移,不同节点上的同一份数据总是在向趋同的方向变化。简单说,就是在一段时间后,节点间的数据会最终达到一致状态。如:TCC和消息队列模式、Saga模式属于最终一致性的解决方案。

了解了分布式事务中的强一致性和最终一致性理论,下面介绍几种常见的分布式事务的解决方案。

Seata 分布式事务

什么是Seata?

Seata是一款阿里巴巴开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务。Seata将为用户提供了 AT、TCC、SAGA 和 XA 事务模式,为用户打造一站式的分布式解决方案。

什么是Seata 的AT模式?

AT模式的特点就是对业务无入侵式,整体机制分二阶段提交

整体机制:两阶段协议的演变

一阶段:业务数据和回滚日志记录在同一个本地事务中提交,释放本地锁和连接资源。

二阶段:提交异步化,非常快速地完成;回滚通过一阶段的回滚日志进行反向补偿。

Seata术语

在 AT 模式下,用户只需关注自己的业务SQL,用户的业务SQL 作为一阶段,Seata 框架会自动生成事务的二阶段提交和回滚操作。

Seata 的AT模式使用场景

怎么理解AT模式呢,咱们以占用库存和创建订单为例:

下面为你介绍一下AT模式下的占库存和生单流程拆解如下:

第一阶段(占用库存过程)

第一阶段(创建订单过程)

第二阶段:提交或回滚

AT模式下如何保证数据一致的?

一阶段提交如何保持一致性?

二阶段如何保持一致性的?

异常阶段如何保持一致性?

异常:TM执行失败,通知TC全局回滚,TC此时通知所有的RM进行回滚,根据undo_log反向操作,使用before image还原业务数据,删除undo_log,但在还原前要首先要校验脏写,对比“数据库当前业务数据”和 “after image”,如果两份数据完全一致就说明没有脏写,可以还原业务数据,如果不一致就说明有脏写,出现脏写就需要转人工处理了。

什么是Seata 的TCC模式?

TCC 模式需要用户根据自己的业务场景实现 Try、Confirm 和 Cancel 三个操作;事务发起方在一阶段执行 Try 方式,在二阶段提交执行 Confirm 方法,二阶段回滚执行 Cancel 方法

相应的,TCC模式(try-confirm-cancel),不依赖于底层数据资源的事务支持:

所谓 TCC 模式,是指支持把自定义的分支事务纳入到全局事务的管理中。

Seata 的TCC模式使用场景

怎么理解TCC模式呢,咱们还以下单扣库存为例,Try 阶段去占库存,Confirm 阶段则实际扣库存,如果库存扣减失败 Cancel 阶段进行回滚,释放库存。

TCC不存在资源阻塞的问题,因为每个方法都直接进行事务的提交,一旦出现异常通过则 Cancel 来进行回滚补偿,这也就是常说的补偿性事务,拆解流程请看下图:

占用库存storage TCC流程图如下

订单系统 order TCC流程图如下

小结

当占用库存成功同时订单下成功时,提交全局事务,当接入TCC模式,最重要的事情就是考虑如何将业务模型拆成2阶段,实现成TCC的3个方法,并且保证Try成功Confirm一定能成功。相对于AT模式,TCC模式对业务代码有一定的侵入性,但是TCC模式无AT模式的全局行锁,TCC性能会比AT模式高很多。

Seata 的TCC模式变种实现方案?

在说TCC变种简化变种方案前,先说一说现实的业务场景:

现实业务并不一定如我们所愿,在业务已成规模,订单系统 和 库存系统,都是在分布式场景,各自的业务接口,各自的DB表,如何保证数据一致呢?

已实现逻辑采用业务代码异常调用返向补偿实现的,伪代码如下:

try{
   占用库存()
   try{
     下单方法()
   }cach(){
   释放库存();
   取消订单();
   }  
}cach(){
  释放库存();
}

流程图如下:

基于现有逻辑如何改造成分布式事务实现方案呢

方案1:采用AT模式,需要做的工作:

缺点:需要对库存业务库和订单业务库存分别存加 undo_log表,事务相对比较长。

方案2:采用Seata TCC模式

缺点:业务代码要写库存锁定状态业务逻辑+订单创建中的中间态。

从上面两个方案不难看出都有一个通病,都需要业务代码改造,侵入强,耦合度高,能否有一种,即不需要业务代码改造成本又低的方案呢?

方案3:接下来的方案是在TCC模式上做了些简化:

缺点:浪费了一次commit空提交 IO交互。

优点:业务侵入性小,可以适应现有业务场景,偶合度低。

简化版本的TCC实现方案的时序图如下:

Seata TCC分布式场景下如何保证幂等呢?

首先说一下什么是幂等?

幂等意思:通常指对同一个系统,使用同样的条件,一次请求和重复的多次请求对系统资源的影响是一致的.因为网络抖动或拥堵可能会超时,事务管理器会对资源进行重试操作,所以很可能一个业务操作会被重复调用,为了不因为重复调用而多次占用资源,造成业务脏数据,就需要保证幂等性。

如何保证幂等呢?

此时需要对服务设计时进行幂等控制,通常我们可以用事务xid或业务主键判重来控制,或采用业务唯一标识来做幂等,总之还是需要业务自己来保证幂等的。

Seata下的Saga模式?

1.Saga是一种补偿协议,Saga 理论出自 Hector & Kenneth 1987发表的论文 Sagas,其核心思想是将长事务拆分为多个本地短事务。

解决了什么问题

2.Saga模式是seata提供的长事务解决方案,在Saga模式中,业务流程中每个参与者都提交本地事务,当出现某一个参与者失败则补偿前面已经成功的参与者,一阶段正向服务和二阶段补偿服务都由业务开发实现。

如图:T1T3都是正向的业务流程,都对应着一个冲正逆向补偿操作C1C3

适用场景

优势

缺点

Saga 模式由于一阶段已经提交本地数据库事务,且没有进行“预留”动作,所以不能保证隔离性。后续会讲到对于缺乏隔离性的应对措施。

seata分布式事务常见问题

常见问题答疑

问:Seata框架如何来保证事务的隔离性的

:因seata一阶段本地事务已提交,为防止其他事务脏读脏写需要加强隔离。

1.读隔离:Seata(AT 模式)的默认全局隔离级别是读未提交,必须要求全局的读已提交 ,目前 Seata 的方式是通过select语句加for update代理方法增加@GlobalLock+@Transactional或@GlobalTransaction实现。

2.写隔离:

问:脏数据回滚失败如何处理

答:1.脏数据需手动处理,根据日志提示修正数据或者将对应undo删除(可自定义实现FailureHandler做邮件通知或其他人工介入操作)。

2.关闭回滚时undo镜像校验,不推荐该方案。

注意事项:建议事前做好隔离保证无脏数据。

问:Seata支持哪些RPC框架?

答:1. AT 模式支持:Dubbo、Spring Cloud、Motan、GRPC 和 Sofa-RPC。

2. TCC 模式支持:Dubbo、Spring Cloud和Sofa-RPC。

问:Seata现阶段支持哪些分库分表解决方案?

:现阶段只支持ShardingSphere。

问:Seata目前支持高可用吗?

答:支持

1.tc使用db模式共享全局事务会话信息,注册中心使用非file的seata支持的第三方注册中心。

2.注册中心包含:eureka、consul、nacos、etcd、zookeeper、sofa、redis、file (直连)。

小结:

分布式方案对比

Seata针对不同的业务场景提供了四种不同的事务模式,对比如下:

后记

本文介绍了分布式事务的一些基础理论,主要对Seata分布式事务方案进行了讲解,在文章的后半部分主要给出了各种方案的常用场景。分布式事务本身就是一个技术难题,业务中具体使用哪种方案还是需要根据自身业务特点自行选择,每种方案在实际执行过程中需要考虑的点都非常多,复杂度较大,所以在非必要的情况下,分布式事务能不用就尽量不用,希望对大家有所帮助。

上一篇 下一篇

猜你喜欢

热点阅读