分布式事务

介绍

最近遇到了一个业务场景,需要做一个工具,将两个业务写数据库合并到一个读数据库。在读写过程中需要做跨库的事务操作,也就是分布式事务。简单来说,就是要同时往两个数据库写数据,要求这个写操作要作为一个事务。

于是学习了一些分布式事务的知识,做一下汇总。

分布式事务解决方案

主要有以下几种的解决方案:

  • XA事务/两阶段提交(2PC)
  • 三阶段提交(3PC)
  • 补偿事务(TCC)
  • 本地消息表
  • 消息事务
  • 最大努力通知
  • Sagas事务模型

XA事务/两阶段提交

是MySQL分布式事务的实现方式。它主要有三个组件组成:

  • **事务管理器(Transaction Manager, TM)**:负责协调分布式事务
  • **资源管理器(Resource Manager, RM)**:负责管理本地资源(如 MySQL 数据库)。
  • XA 事务 ID(XID:唯一标识一个分布式事务。

适用于简单的,事务量较小的系统

实现

在 MySQL 中,XA 事务通过以下 SQL 语句实现:

  • XA START:开始一个 XA 事务。
  • XA END:结束一个 XA 事务。
  • XA PREPARE:准备提交事务。
  • XA COMMIT:提交事务。
  • XA ROLLBACK:回滚事务。
  • XA RECOVER:查看处于准备状态的 XA 事务。

原理

XA事务,遵循2PC协议主要有两个工作阶段:

  1. 准备阶段(Prepare Phase):
    • 事务管理器向所有资源管理器发送准备请求。
    • 资源管理器执行本地事务操作,并将结果写入日志,但不提交。
    • 资源管理器向事务管理器反馈是否可以提交。
  2. 提交阶段(Commit Phase)
    • 如果所有资源管理器都准备好,事务管理器发送提交请求。
    • 资源管理器提交本地事务并释放资源。
    • 如果任何一个资源管理器未准备好,事务管理器发送回滚请求。

优缺点

优点:

  • 强一致性:确保所有参与者要么全部提交,要么全部回滚。
  • 跨数据库支持:可以跨多个 MySQL 实例或存储引擎执行分布式事务。

缺点:

  • 性能较低:由于需要多次网络通信和日志写入,XA 事务的性能较低。
  • 单点故障:如果协调者崩溃,事务可能无法完成。
  • 阻塞问题:在准备阶段,参与者需要锁定资源并等待协调者的指令,可能导致长时间阻塞。

使用场景

  • 跨数据库事务:在多个 MySQL 实例之间执行分布式事务。
  • 跨存储引擎事务:在 InnoDB 和 MyISAM 等不同存储引擎之间执行事务。
  • 微服务架构:在微服务架构中,确保跨服务的分布式事务一致性。

改进

为了解决2PC的缺点,提出了新方案

  • 三阶段提交(3PC)
  • Paxos或Raft协议
  • 消息事务(基于消息的最终一致性)

三阶段提交(3PC)

3PC对比2PC,增加了两个功能,增加预提交阶段阶段和超时机制

适用于对一致性和可用性有一定需求的场景

原理

在准备阶段之后添加了预提交的阶段:

  • 预提交阶段(Pre-Commit Phase)
    • 如果所有参与者都同意提交,协调者发送 Pre-Commit 请求。
    • 参与者进入预提交状态,锁定资源并准备提交。

优缺点

优点:
预提交阶段主要解决了2PC的一下几个痛点

  1. 减少阻塞时间: 2PC会因为协调者的故障而长时间的阻塞,添加预提交阶段后,参与者可以通过超时机制,自行决定提交或者回滚,减少阻塞时间。
  2. 提高容错能力: 在预提交阶段,3PC的参与者会锁定资源,及时协调者故障,也可以通过超时机制恢复

缺点:

  1. 实现更复杂
  2. 性能开销依旧大
  3. 极端条件下还是会出现数据不一致

结尾

业务主要是简单的业务,所以我直接使用了XA事务的方式,剩下其他的方式之后可以深入了结。