首页 > 其他 > 详细

从本地事务到分布式事务到微服务下事务

时间:2019-11-20 16:43:39      阅读:92      评论:0      收藏:0      [点我收藏+]

从本地事务到分布式事务到微服务下事务

 

一、传统本地事务

    传统单服务器,单关系型数据库下事务比较简单,完全可用很简单的实现ACID,实际中我们实现一个业务时只需要:开启一个事务-操作数据库-提交/回滚这个事务,这样就完美的实现了一次事务操作,更简单点我们通常会通过spring集成事务直接指定在哪些服务什么样的方法执行什么样的事务即可,更甚至我们业务实现基本都忽略了事务,具体图如下:

技术分享图片

二、传统分布式事务

    在传统一服务,一个关系数据库架构基础上,随着访问量的增大,单机很明显已满足不了现状,于是我们顺其自然的就考虑到了服务集群部署,数据库分库分表,从而也就实现了这样一个样子,如图:

技术分享图片

解释:服务水平扩展,数据库分库分表压力是将下来了,但同时也来了另一个问题,如果我一次请求中同时操作了多个DB这个时候我们的传统事务模式(一)就已经不行了,于是我们就在网上各种搜,终于找到了一个叫2PC(二阶段提交)的东西,具体操作如图:

技术分享图片

大概意思:

在最外层有一个事务管理器(TM)来控制整个事务,一个请求过来,

第一阶段:事务管理器通知各个资源管理器(RM)准备提交事务,这时我们处理完业务各个RM准备完毕后给TM一个响应(业务正常/异常)

第二阶段:1、如果反馈TM业务正常那么TM会通知RM可提交事务,如果异常,通知回滚事务

大概就是这个意思,具体可百度


三、微服务下事务

     分布式系统,随着业务的不断增加,系统更新、上线频繁,出错率高,于是我们就想到了按照不同的业务线将系统、DB进行拆分形成单独部署的小颗粒系统,系统之间只能通过api的形式调用,而不同于之前的直接操作库表,如图:

技术分享图片

于是就带来了以下问题:

本系统只能控制本DB事务,通过api调用的无法控制,从而导致了数据不一致的情况

于是我们最简单的想法就是,我将本地业务和调用远程服务放到一个系统,如果远程服务报错我就回滚,如图:

技术分享图片

很快我们又发现了问题:

1、如果调用外部服务时耗时较长,那么我们无形中就创建了一个大事务

2、如果因为接口超时远程服务执行成功,那么我们本地回滚,导致数据不一致

最终解决方案:

1、利用消息达到最终一致性

2、TCC

下次写消息确保事务的最终一致性

 

 

Java中的事务——全局事务与本地事务

上一篇文章中说到过,Java事务的类型有三种:JDBC事务、JTA(Java Transaction API)事务、容器事务。这是从事务的实现角度区分的,本文从另外一个角度来再次区分一下Java中的事务。

站在事务管理的角度,可以把Java中用到的事务分为本地事务和全局事务。

技术分享图片

本地事务

不用事务的编程框架来管理事务,直接使用资源管理器来控制事务。典型的就是java.sql.Connection 中的 setAutoCommitcommitrollback方法。

技术分享图片

本地事务的优点

  • 支持严格的ACID属性
  • 可靠
  • 高效
  • 状态可以只在资源管理器中维护
  • 应用编程模型简单

本地事务的局限

  • 不具备分布式事务处理能力
  • 隔离的最小单位由资源管理器决定,如数据库中的一条记录

本地事务比较简单,对事务不太了解的同学可以阅读我的博客中其他关于事务的内容

全局事务

前面我们介绍了本地事务,本地事务是我们在编程中比较常接触的事务,比如典型的jdbc操作,在保证ACID方面做的非常出色。但是本地事务无法解决分布式场景中的事务问题。

前面的文章中专门介绍过分布式场景中为什么需要事务。这里我再稍微回顾一下。

典型的分布式事务场景

  • 转账

    • 对于银行账户间转账的问题。账户A向账户B转账,从实现上来看,一般可以拆分为“从账户A中扣钱”、“向账户B中加钱”两个操作步骤,两个账户大多数情况下会被切分到不同的数据库上,更多的是,两个操作会是两次服务调用。这两个操作要求做到要么同时成功、要么同时失败。因此引入了分布式事务问题。
  • 下单

    • 在电商网站上,在消费者点击购买按钮后,交易后台会进行库存检查、下单、减库存、更新订单状态等一连串的服务调用,每一个操作对应一个独立的服务,服务一般会有独立的数据库,因此会产生分布式事务问题。

由于用一次操作,数据要写入的数据库不一致,或者调用的服务都是RPC服务,那么就会无法保证操作在同一个事务中被处理掉。所以就会存在分布式的事务问题。


全局事务的定义

在上面的场景中会出现分布式事务问题,那么全局事务就是一个标准的分布式事务。下面我们尝试着给全局事务下一个定义:

全局事务是由资源管理器管理和协调的事务。

全局事务是一个DTP模型的事务,所谓DTP模型指的是X/Open DTP(X/Open Distributed Transaction Processing Reference Model),是X/Open 这个组织定义的一套分布式事务的标准,也就是了定义了规范和API接口,由这个厂商进行具体的实现。

技术分享图片

X/Open DTP 定义了三个组件:APTMRM 和两个协议:XATX

AP(Application Program):也就是应用程序,可以理解为使用DTP的程序

RM(Resource Manager):资源管理器,这里可以理解为一个DBMS系统,或者消息服务器管理系统,应用程序通过资源管理器对资源进行控制。

TM(Transaction Manager):事务管理器,负责协调和管理事务,提供给AP应用程序编程接口以及管理资源管理器。

XA协议:应用或应用服务器与事务管理之前通信的接口

TX协议:全局事务管理器与资源管理器之间通信的接口

事务管理器控制着全局事务,管理事务生命周期,并协调资源。资源管理器负责控制和管理实际资源。

这里还要提到一个点,就是2PC(两阶段提交),在全局事务中,为了保证所有的操作可以一次性要么全提交,要么全失败。事务管理器和资源管理器之间的事务操作的控制是采用2PC来进行的,关于2PC,我博客中有文章专门介绍,这里不再赘述。

J2EE中全局事务的实现

Java自身提供了一些API可以用来实现全局事务。Java中的事务——JDBC事务和JTA事务中介绍的JTA事务就可以用来实现J2EE中的全局事务。

技术分享图片

JTA(Java Transaction API):面向应用、应用服务器与资 源管理器的高层事务接口。

JTS(Java Transaction Service):JTA事务管理器的实现标 准,向上支持JTA,向下通过CORBA OTS实现跨事务域的互 操作性。

EJB:基于组件的应用编程模型,通过声明式事务管理进一步 简化事务应用的编程。

全局事务的优缺点

全局事务,作为一种标准的分布式事务解决方案,他解决了本地事务无法满足分布式场景中数据的ACID的要求。

关于分布式事务、两阶段提交协议、三阶提交协议中我曾经介绍过,2PC本身是存在同步阻塞问题,这就会导致效率变低,所以,采用2PC进行事务控制的全局事务也必然存在效率低的问题。这也是全局事务最致命的缺点,在提倡微服务的今天,这是不能容忍的。

总结

本文主要介绍了本地事务和全局事务,本地事务很简单,在Java中可以使用JDBC来实现本地事务,全局事务是一种基本的分布式事务解决方案,是符合DTP模型的事务管理机制。

目前,越来越多的web开发要涉及到分布式事务,尤其是微服务架构最近越来越火,在微服务架构中,分布式事务是必然存在的。对于分布式事务的处理,本文主要介绍了一个典型的方案——全局事务。但是实际上,低效率的全局事务并不是很适合用来解决大型网站的分布式事务问题。

在业内,主要用来解决分布式事务的方案是使用柔性事务。柔性事务包括几种类型:两阶段型、补偿型、异步确保型和最大努力通知型。后面我会有文章继续介绍柔性事务。请继续关注。

 
 

从本地事务到分布式事务到微服务下事务

原文:https://www.cnblogs.com/leijiangtao/p/11898640.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!