分布式事务介绍
本地事务
本地事务:支持事务的参与者、服务器、资源管理器(RM)和事务管理器(TM)位于单机之上,仅限对单一数据库资源的访问控制。就是表和数据库位于一个服务器上,事务的操作都在这一个服务器上进行。
起初,事务仅限于对单一数据资源的访问控制:
而我们的本地事务由资源管理器进行管理:
事务的ACID是通过InnoDB日志和锁来保证。事务的隔离性是通过事务的锁机制实现的,持久性通过redo log(重做日志)来实现,原子性和一致性通过Undo log来实现。UndoLog的原理很简单,为了满足事务的原子性,在操作任何数据之前,首先将数据备份到一个地方(这个存储数据备份的地方称为UndoLog)。然后进行数据的修改。如果出现了错误或者用户执行了ROLLBACK语句,系统可以利用Undo Log中的备份将数据恢复到事务开始之前的状态。 和Undo Log相反,RedoLog记录的是新数据的备份。在事务提交前,只要将RedoLog持久化即可,不需要将数据持久化。当系统崩溃时,虽然数据没有持久化,但是RedoLog已经持久化。系统可以根据RedoLog的内容,将所有数据恢复到最新的状态。
本地事务主要限制在单个会话内,不涉及多个数据库资源。但是在基于SOA(Service-Oriented Architecture,面向服务架构)的分布式应用环境下,越来越多的应用要求对多个数据库资源,多个服务的访问都能纳入到同一个事务当中,分布式事务应运而生。
分布式事务
在开发中,为了降低单机的压力,通常会进行分表分库,将表分布在不同的数据库中(数据库有可能分布在不同的机器上),但是一个业务场景可能会处理不同库中的表,事务的提交就不能在像单机那样处理,因为涉及到多个服务器的控制,要考虑服务器之间的通信是否正常、网络延时带宽等因素,这些在单机上并没有太大的影响。所以说多服务器之间事务的控制变得相对复杂,分布式事务也就相应的出现。
比如原来单机支撑了整个电商网站,现在对整个网站进行拆解,分离出了订单中心、用户中心、库存中心等,对于订单中心,有专门的数据库存储订单信息,用户中心也有专门的数据库存储用户信息,库存中心也会有专门的数据库存储库存信息,如果要同时对订单和库存进行操作,那么就会涉及到订单数据库和库存数据库,为了保证数据一致性,就需要用到分布式事务。
分布式事务:分布式事务就是指事务的参与者、支持事务的服务器、资源服务器以及事务管理器分别位于不同的分布式系统的不同节点之上。简单的说,就是一次大的操作由不同的小操作组成,这些小的操作分布在不同的服务器上,且属于不同的应用,分布式事务需要保证这些小操作要么全部成功,要么全部失败。本质上来说,分布式事务就是为了保证不同数据库的数据一致性。
最早的分布式事务应用架构不涉及服务之间的访问调用,仅仅是服务内操作涉及对多个数据库资源的访问。
当一个服务操作访问不同的数据库资源,又希望对它们的访问具有事务特性时,就需要采用分布式事务来协调所有的事务参与者。
在上面的分布式事务应用架构中,尽管一个服务操作会访问多个数据库资源,但是毕竟整个事务还是控制在单一服务的内部。如果一个服务操作需要调用另外一个服务,这时的事务就需要跨越多个服务了。在这种情况下,起始于某个服务的事务在调用另外一个服务的时候,需要以某种机制流转到另外一个服务,从而使被调用的服务访问的资源也自动加入到该事务当中来。下图反映了这样一个跨越多个服务的分布式事务:
如果将上面这两种场景(一个服务可以调用多个数据库资源,也可以调用其他服务)结合在一起,对此进行延伸,整个分布式事务的参与者将会组成如下图所示的树形拓扑结构。在一个跨服务的分布式事务中,事务的发起者和提交均系同一个,它可以是整个调用的客户端,也可以是客户端最先调用的那个服务。
分布式事务的解决方案
分布式事务是最核心的还是其ACID特性。研究分布式事务本质上还是研究其是如何保证ACID的。事务模型为分布式事务提供了理论基础,像2PC、3PC协议则是实现分布式事务的设计方案。
X/Open XA协议
DTP模型( X/Open Distributed Transaction):最早的分布式事务模型,是由 X/Open 国际联盟提出的,也就是X/Open XA协议,简称XA协议。
DTP模型包含一个全局事务管理器(TM Transaction Manager)和多个资源管理器(RM Resource Manager)。全局事务管理器负责管理全局事务状态与参与的资源,协同资源一起提交或回滚;资源管理器负责具体的资源操作。
XA协议描述了TM与RM之间的接口,允许多个资源在同一分布式事务中访问。
TM:Transaction Manager 事务管理器
- 分布式事务的实现由事务管理器来完成,它会提供分布式事务的操作接口供我们的业务系统调用。这些接口称为TX接口。
- 事务管理器还管理着所有的资源管理器,通过它们提供的XA接口来统一调度这些资源管理器,以实现分布式事务。
- DTP只是一套实现分布式事务的规范,并没有定义具体如何实现分布式事务,TM可以采用2PC、3PC、Paxos等协议实现分布式事务。
RM:Resource Manager 资源管理器
- 能够提供数据服务的对象都可以是资源管理器,比如:数据库、消息中间件、缓存等。大部分场景下,数据库即为分布式事务中的资源管理器。
- 资源管理器能够提供单数据库的事务能力,它们通过XA接口,将本数据库的提交、回滚等能力提供给事务管理器调用,以帮助事务管理器实现分布式的事务管理。
- XA是DTP模型定义的接口,用于向事务管理器提供该资源管理器(该数据库)的提交、回滚等能力。XA协议实现通常在RM层。
- DTP只是一套实现分布式事务的规范,RM具体的实现是由数据库厂商来完成的。
基于 DTP 模型的分布式事务流程大致如下:
-
应用程序(AP)向TM申请开始一个事务
-
针对要操作的 RM,AP 会先向 TM 注册(TM 负责记录 AP 操作过哪些 RM,即分支事务),TM 通过 XA 接口函数通知相应 RM 开启分布式事务的子事务,接着 AP 就可以对该 RM 管理的资源进行操作。
-
当 AP 对所有 RM 操作完毕后,AP 根据执行情况通知 TM 提交或回滚该全局事务,TM 通过 XA 接口函数通知各 RM 完成操作。TM 会先要求各个 RM 做预提交,所有 RM 返回成功后,再要求各 RM 做正式提交,XA 协议要求,一旦 RM 预提交成功,则后续的正式提交也必须能成功;如果任意一个 RM 预提交失败,则 TM 通知各 RM 回滚。
-
所有 RM 提交或回滚完成后,全局事务结束。
1、原子性
XA协议使用2PC(Two Phase Commit 两阶段提交)原子提交协议来保证分布式事务原子性。
两阶段提交是指将提交过程分为两个阶段:准备阶段(投票阶段)和提交阶段(执行阶段)。
-
准备阶段
TM向每个RM发送准备消息。如果 RM 的本地事务操作执行成功,则返回成功;如果 RM 的本地事务操作执行失败,则返回失败。
-
提交阶段
如果 TM 收到了所有 RM 回复的成功消息,则向每个 RM 发送提交消息;否则发送回滚消息;RM 根据 TM 的指令执行提交或者回滚本地事务操作,释放所有事务处理过程中使用的锁资源。
存在的问题:
同步阻塞:当参与事务者存在占用公共资源的情况,其中一个占用了资源,其他事务参与者就只能阻塞等待资源释放,处于阻塞状态。并发性差。
单点故障:一旦事务管理器出现故障,整个系统不可用
数据不一致:在阶段二,如果事务管理器只发送了部分 commit 消息,此时网络发生异常,那么只有部分参与者接收到 commit 消息,也就是说只有部分参与者提交了事务,使得系统数据不一致。
2、隔离性
XA 协议中没有描述如何实现分布式事务的隔离性,但是 XA 协议要求 DTP 模型中的每个 RM 都要实现本地事务,也就是说,基于 XA 协议实现的分布式事务的隔离性是由每个 RM 本地事务的隔离性来保证的,当一个分布式事务的所有子事务都是隔离的,那么这个分布式事务天然的就实现了隔离性。
以 MySQL 来举例,MySQL 使用 2PL(Two-Phase Locking,两阶段锁)机制来控制本地事务的并发,保证隔离性。2PL 与 2PC 类似,也是将锁操作分为加锁和解锁两个阶段,并且保证两个阶段完全不相交。加锁阶段,只加锁,不放锁。解锁阶段,只放锁,不加锁。
如上图所示,在一个本地事务中,每执行一条更新操作之前,都会先获取对应的锁资源,只有获取锁资源成功才会执行该操作,并且一旦获取了锁资源就会持有该锁资源直到本事务执行结束。
MySQL 通过这种 2PL 机制,可以保证在本地事务执行过程中,其他并发事务不能操作相同资源,从而实现了事务隔离。
3、一致性
前面提到一致性有两层语义,一层是确保事务执行结束后,数据库从一个一致状态转变为另一个一致状态。另一层语义是事务执行过程中的中间状态不能被观察到。
TCC模型
TCC(Try-Confirm-Cancel)分布式事务模型相对于 XA 等传统模型,其特征在于它不依赖资源管理器(RM)对分布式事务的支持,而是通过对业务逻辑的分解来实现分布式事务。
TCC 模型认为对于业务系统中一个特定的业务逻辑,其对外提供服务时,必须接受一些不确定性,即对业务逻辑初步操作的调用仅是一个临时性操作,调用它的主业务服务保留了后续的取消权。如果主业务服务认为全局事务应该回滚,它会要求取消之前的临时性操作,这就对应从业务服务的取消操作。而当主业务服务认为全局事务应该提交时,它会放弃之前临时性操作的取消权,这对应从业务服务的确认操作。每一个初步操作,最终都会被确认或取消。
TCC事务机制相比于上面介绍的XA,解决了其几个缺点:
-
解决了协调者单点,由主业务方发起并完成这个业务活动。业务活动管理器也变成多点,引入集群。
-
同步阻塞:引入超时,超时后进行补偿,并且不会锁定整个资源,将资源转换为业务逻辑形式,粒度变小。
-
数据一致性,有了补偿机制之后,由业务活动管理器控制一致性
MySQL分布式事务
MySQL 的 InnoDB 引擎其实能够支持分布式事务,也就是我们经常说的 XA 事务;XA 事务就是用了我们在上一节中提到的两阶段提交协议实现分布式事务,其中事务管理器为协调者,而资源管理器就是分布式事务的参与者。
参考