D 的个人博客

全职做开源,自由职业者

  menu

分布式事务原理

本文是对分布式事务原理、规范的科普,主要围绕两阶段提交协议展开。最后描述了在应用框架层面模拟两阶段提交协议的简化设计。

1 事务/分布式事务

1.1 事务

事务是数据库从一个稳定状态变迁到另一个稳定状态的保证,具备 ACID 这 4 个特性:

  • 原子性(Atomicity):一个事务中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节。事务在执行过程中发生错误,会被回滚到事务开始前的状态。
  • 一致性(Consistency):在事务开始之前和事务结束以后,数据库的完整性限制没有被破坏。
  • 隔离性(Isolation):两个事务的执行是互不干扰的,两个事务时间不会互相影响。
  • 持久性(Durability):在事务完成以后,该事务对数据库所作的更改便持久地保存在数据库之中,并且是完全的。
例如应用程序需要更新多条相关数据时就需要进行事务处理。
 

1.2 分布式事务与 XA 规范

分布式事务是指会涉及到操作多个数据库的事务,同样必须保证 ACID。
其就是将对同一库事务的概念扩大到了对多个库的事务:对同一库的 SQL 操作对应了分布式事务中对一个库的事务。
 
X/Open XA 定义了分布式事务处理的规范,并由数据库厂商在驱动层面进行实现。XA 规范的基础是两阶段提交协议,并定义了分布式事务处理所涉及的角色:
  • 应用程序(AP)
  • 事务管理器(TM)
  • 资源管理器(RM)
  • 通信资源管理器(CRM)
可以这样认为,事务管理器即事务处理中间件(分布式事务处理系统);资源管理器即各个数据库。

2 两阶段提交协议

两阶段提交协议(Two-phase commit protocol, 2PC)将一次分布式事务处理划分为两个阶段:预提交阶段(也称为准备阶段或投票阶段),提交阶段。

2.1 预提交阶段

这是两阶段提交协议的第一个阶段,分布式事务处理系统咨询各个资源管理器是否可以提交本地事务,各个资源管理器会把这个咨询过程写入日志,以便进行回滚或提交。

 

当一个数据库接收到咨询后,它会将需要执行的操作写入日志,禁止其他写入操作(锁定资源)。

如果分布式事务中某数据库预提交失败或提交失败,那该数据库会根据日志进行自身的操作回滚,并解锁。

2.2 提交阶段

分布式事务处理系统对各个资源管理器下达提交/回滚的指令,使整个分布式事务结束。

 

当一个数据库接受到提交/回滚指令时,它将根据第一阶段的日志进行提交/回滚处理。

 

两阶段提交协议可以在数据库层面通过驱动支持,也可以在应用框架中按照其原理进行设计实现。

3 分布式事务应用框架

使用数据库驱动方式实现两阶段事务有两个不足:

  • 随着分布式事务的参与者增多,效率会明显降低
  • 对应用开发者透明,调试不便
  • 必须依赖数据库,不是所有数据库都实现了 XA 规范

3.1 角色

  • 发起者:分布式事务发起者,需要提供回查恢复接口
  • 参与者:参与到分布式事务的其他系统,提供提交/回滚接口。这里的提交/回滚接口即是对数据库数据的 SQL 操作。
  • 活动管理器:负责管理分布式事务(活动、操作)。
  • 定时器:触发对分布式事务活动的捞取,以备回查恢复。

3.2 交互时序

两阶段提交时序:

两阶段提交时序
 
 
因为系统在上述交互中不是绝对可靠的,所以需要一定的方式进行事务状态恢复,保证所有参与者最终一致。

回查恢复时序:

回查恢复时序

3.3 关键点

  • 参与者提供的提交/回滚接口必须满足幂等性,即定时触发重复调用提交/回滚时不会重复操作同一资源
  • 根据发起者生成 txId,回查恢复时根据 txId 调用发起者回查恢复接口
  • 活动管理器与发起者同库/不同库时,事务活动、操作状态变迁的不同处理
  • 事务内调用操作的顺序
  • 定时任务定时间隔/重试次数

参考