什么是分布式事务?


作为一名软件工程师,我一直想知道事务是如何工作的,以及它们在分布式系统中是如何管理的,所以我用谷歌搜索了一下,发现了很多模式和规范,比如 JTA、2PC、SAGA、事件驱动架构、发件箱等……

在本文中,我将概述分布式事务,并尝试解释两阶段提交模式。

什么是事务?
在编程中,事务是指作为单个原子工作单元执行的一系列操作。事务的关键特征是它是原子的、一致的、隔离的和持久的( ACID )。

  • 原子的:这意味着事务是一个全有或全无的操作。如果事务的一部分失败,则整个事务将回滚到之前的状态。
  • 一致:事务将系统从一个有效状态移动到另一个有效状态。
  • Isolated:一个事务与其他事务隔离,这意味着一个事务所做的更改在当前事务提交之前对其他事务不可见。
  • 持久:事务的更改以永久方式记录,并在任何后续系统故障中幸存下来。

在单体应用中,由于应用的所有组件紧密耦合并运行在同一个进程中,因此管理事务相对容易,因此很容易保持一致性、隔离和回滚更改(如果需要),但问题会出现我们转向分布式系统,例如微服务应用程序或与两个或多个数据库交互的应用程序。在这种情况下,由于微服务分布在多个机器和进程中,因此很难维护事务的ACID属性。

分布式事务:
分布式事务是一种涉及多个数据库或分布在不同服务器上的其他资源的事务。它用于协调这些资源的动作,以确保事务所做的更改是原子的、一致的、隔离的和持久的 (ACID)。

为了演示分布式事务的使用,我们将举一个处理在线支付的服务的简单示例。
第一个数据库包含发送方的数据,第二个数据库包含接收方的数据。现在,让我们了解这个过程:

--- DB-1 ----
begin_transaction();
update_account_balance(from_account, -amount);
commit_transaction();
--- DB-2 ----
begin_transaction();
update_account_balance(to_account, amount);
commit_transaction();


此解决方案的问题在于,如果其中一个数据库中的任何事务失败,则数据将不一致,因为第二个数据库不知道这一点并且它将提交事务。
有许多模式可以解决这个问题。其中之一是两阶段提交。

了解两阶段提交:

两阶段提交(2PC)是一种用于在分布式系统中实现原子提交的协议,这意味着系统中的所有参与节点要么提交事务,要么都不提交。
该协议由两个阶段组成:准备阶段和提交阶段。

在准备阶段,系统中的每个节点投票决定提交或中止事务,在提交阶段,协调器根据收到的选票向所有节点发送提交或中止消息。
Java 实现:JTA 或 Java 事务 API:

Java Transaction API (JTA) 允许应用程序执行分布式事务。JTA 指定了事务管理器和分布式事务系统中涉及的各方之间的标准 Java 接口:

  • 应用程序:我们的 Java 应用程序
  • 应用服务器: Java EE 框架,提供运行 Java 应用程序的容器(例如 WebLogic、GlassFish、WildFly)
  • 事务管理器:允许应用程序服务器划分和控制事务的接口(例如 JDBC 驱动程序管理器、JTA)
  • 资源适配器:允许应用程序与资源管理器(例如 JDBC 驱动程序)通信的接口
  • 资源管理器:管理特定资源的软件组件,例如数据库、消息队列或其他参与分布式事务的事务系统(例如 SQL 数据库)


事务管理器周围的编号框对应于 JTA 的三个接口部分:

  1.  UserTransaction  — javax.transaction.UserTransaction 接口为应用程序提供了以编程方式控制事务边界的能力。javax.transaction.UserTransaction 方法启动全局事务并将事务与调用线程相关联。
  2. 事务管理器 ——javax.transaction.TransactionManager 接口允许应用服务器代表被管理的应用程序控制事务边界。
  3.  XAResource  — javax.transaction.xa.XAResource 接口是基于 X/Open CAE 规范(分布式事务处理:XA 规范)的行业标准 XA 接口的 Java 映射。

请注意,一个关键链接是 JDBC 驱动程序对 XAResource 接口的支持。JDBC 驱动程序必须支持通过应用程序和/或应用程序服务器的正常 JDBC 交互(本地事务),以及 JTA 的 XAResource 部分(全局事务)。

结论:
分布式事务是每个分布式系统中的关键部分,尽管两阶段提交解决了这个问题。有一些限制:

  • 两阶段提交很慢,因为所有服务都需要等待最慢的服务才能提交事务。
  • 服务之间的紧密耦合。
  • 它不支持NoSQL 数据库。

软件工程师提出了一种超越这些限制的新模式,这就是SAGA 模式。