在上一篇文章中说到过, Java 事务的类型有三种: JDBC 事务, JTA(Java Transaction API) 事务, 容器事务.
这是从事务的实现角度区分的, 本文从另外一个角度来再次区分一下 Java 中的事务. 站在事务管理的角度, 可以把 Java 中用到的事务分为本地事务和全局事务.
本地事务
不用事务的编程框架来管理事务, 直接使用资源管理器来控制事务. 典型的就是 java.sql.Connection 中的 setAutoCommit,commit,rollback 方法. 之前我们介绍的 JDBC 事务就是一个非常典型的本地事务. 本地事务也是我们日常开发中最经常使用的事务.
本地事务的优点
支持严格的 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 定义了三个组件: AP,TM,RM 和两个协议: XA,TX
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 开发要涉及到分布式事务, 尤其是微服务架构最近越来越火, 在微服务架构中, 分布式事务是必然存在的. 对于分布式事务的处理, 本文主要介绍了一个典型的方案 -- 全局事务. 但是实际上, 低效率的全局事务并不是很适合用来解决大型网站的分布式事务问题.
在业内, 主要用来解决分布式事务的方案是使用柔性事务. 柔性事务包括几种类型: 两阶段型, 补偿型, 异步确保型和最大努力通知型. 后面我会有文章继续介绍柔性事务
来源: http://blog.51cto.com/13732225/2132484