分布式事务详解
约 6257 字大约 21 分钟
2025-09-02
分布式事务详解
事务
事务是一个程序执行单元,里面所有的操作要么全部执行成功,要么全部执行失败。
本地事务
在单体应用中,服务使用的是同一个数据源,对于事务的支持可以依赖于数据库的事务。数据库的事务是数据库操作的最小执行单元,它由一组SQL语句组成。它具备四个特性:
- 原子性(Atomic):一个事务中的所有操作要么全部执行成功,要么全部执行失败;
- 一致性(Consistency):事务的执行必须使数据库从一个一致的状态变为另一个一致的状态。也就是说,事务执行前后,所有数据约束(如主键、外键、唯一性、检查约束等)都必须被满足;
- 隔离性(Isolation):多个事务并发执行时,一个事务的执行不影响其他事务的执行。即事务之间相互隔离,互不干扰;
- 持久性(Durability):一旦事务提交成功,它对数据库所有的修改就会永久的保存下去,即使系统发生故障(如断电、崩溃等)也不会丢失;
在单体应用中,单个服务使用单个数据源的场景,它的事务是依赖于数据库本身的提供的事务能力来工作,这种方式事务最基础的一种解决方案,它称之为本地事务。
分布式事务
对于分布式事务而言,它在百度上的解释是:
分布式事务是指事务的参与者、支持事务的服务器、资源服务器以及事务管理器分别位于分布式系统的不同节点之上
上面的描述其实是有点抽象的,但是我们可以借助下面的图来更好的理解什么是分布式事务:

作为电商中最为常见的下发场景,订单服务除了需要的在本地的数据库创建订单数据的时候,还需要通过rpc服务调用库存服务的接口来实现库存的扣减。对于库存服务返回的扣减结果有三种可能:成功、失败或超时。
对于成功和失败的返回结果,如果成功,就继续后面的步骤;反之,就可以回滚订单数据。最难处理的就是超时,因为超时带来的结果是不确定的,无法知道库存服务的库存是扣减成功了还是扣减失败了。极为特殊的情况就是:库存服务扣减成功但是返回结果超时,这种情况下订单服务如果回滚了订单数据,就会出现数据不一致的现象。
分布式事务常见的场景:
跨服务操作
当一个业务流程涉及到多个独立部署的服务时,例如用户在注册后需要同时增加用户积分和创建用户记录,每个操作可能在一个独立的服务中,这些服务之间需要协调完成整个事务;
跨数据库操作
系统可能采用多个数据库实例,例如一个订单数据库和一个交易数据库。当用户发起退款时,需要同时修改订单数据库和交易数据库中的数据,由于涉及到不同的数据库实例,需要分布式事务来保证数据一致性;
不同资源类型的跨节点操作
一个事务可能涉及到数据库、消息队列、缓存系统等不同类型的资源,这些资源分布在不同的节点上,也需要分布式事务来确保整体操作的原子性;
对于上述会出现分布式的场景简单的概括下来就是:当一个事务的中的操作需要多个服务协同完成时,它就需要分布式事务来确保数据的一致性,这个其他服务可以是其他的数据源、其他的服务(例如第三方接口、中间件等等)。
理论基础
在本地事务的处理上我们会依赖于数据库的事务特性,它遵循这个ACID的原则来保证数据的一致性。对于分布式事务而言,它需要按照一定的规则来理论基础来执行,这样才能保证分布式事务的结果是符合预期的。
CAP理论
CAP理论是由计算机科学记 Eric Brewer在2000年提出的一个分布式领域的基础理论。它描述了,在分布式系统中,只能在CAP三个特性中同时满足任意两个, 而无法三者兼得。
CAP理论的核心概念
一致性(Consistency)
一致性简单来说就是分布式系统中的任意节点在同一个时刻看到的数据都是一致的。
可用性(Availability)
系统在有限时间内总能返回一个相应(哪怕不是最新的数据),不会因为部分节点的故障而导致整个系统不可用
分区容错性(Partition Tolerance)
系统在网络分区(即部分节点之间无法通信)的情况下,仍然能继续运行。
CAP理论的基本思想
对于分布式系统而言,CAP的三个特性都是非常重要的,但是我们往往是无法同时满足的。观察下面的例子:

对于数据库集群而言,我们通常会使用主从同步的方式保证各个数据库节点的数据一致性。但是如果主服务器与从服务器之间出现了无法通信,这就会导致主服务器写入的数据无法同步到到从服务器上。
- 假如此时我们需要保证一致性,首先订单服务1向主服务器写入数据的时候必须要保证数据写入到了从服务器,如果从服务器写入失败了,那么主服务器的数据写入就不能是成功的,否则订单服务2从从服务器读取数据的时候就无法读取到最新的数据;亦或是,在主服务器写成功后,订单服务2来查询数据的就需要返回错误信息,而不是对应的数据,也就无法保证可用性;
- 假如此时我们需要保证可用性,那么我们的目标就是订单服务2必须也要能查询到数据,但是主从服务器之间的通信故障,导致主服务器新写入的数据无法同步到从服务器上,所以订单服2必然无法读取到最新的数据,因此它无法保证一致性的。
对于分区容错性而言,如果放弃它,其实分布式系统就失去了意义。因为在分布式系统中,你不允许有节点出现通信故障,这是不可能的,因为网络超时是非常容易发生的。所以对于CAP理论而言,它最常用的实现方案就是CP或者是AP。对于CP而言,它要保证数据的一致性,就会降低系统的吞吐量,它要求所有的数据副本都更新到了最新的状态,否则读取数据的请求就不能返回数据,所以最常用的策略还是AP。
基于Nacos来分析下AP和CP之间的区别
提示
Nacos是阿里巴巴开源的云原生基础服务管理平台,专注于解决分布式系统中的服务治理与配置管理问题,其核心目标是简化为微服务结构的构建与管理,通过整合服务发现、配置管理、服务治理等功能,成为云原生应用核心的基础设施。
CP模式
Nacos Server的CP模式是基于Raft算法,要求集群中超过半数的节点确认写操作后,数据才被视为有效,这种模式的核心特点包括:
- 强一致性:所有的Nacos Server节点的数据始终保持同步;
- 分区容忍性:网络分区时,集群仍能运行,但需要等待多数节点回复后才能写入(选举期间短暂不可用)
适用于需要严格保证数据一致性的业务,如配置管理、基础设施服务注册(如数据库、中间件的元数据)。
CP模式的写操作通过Leader节点协调,因此写入的延迟略高,但能确保数据的全局一致性;

AP模式
Nacos Server的AP模式是默认的模式,优先保障高可用性,其实现基于Distro协议(Nacos自研的AP协议)。采用异步数据复制(内存或分布式存储)和去中心化架构,这种模式的核心特点包括:
- 最终一致性:数据更新后,异步同步到集群其它阶段,允许短暂不一致;
- 高可用性:网络分区时,非Leader节点仍可处理读写请求,不会因为单点故障导致服务终端;
P模式读写请求可以由任意节点处理,响应速度快,但无法保证数据实时一致性。

其实对于CP模式和AP模式,核心在于CP模式下,通常会有主节点和从节点之分,主节点负责写请求,从节点负责读取请求。而在AP模式下,基本上所有的节点都是一样的,没有角色上的区分。
Base理论
eBay架构师 Dan Pritchett 源于对大规模分布式系统的实践总结,在ACM上发表文章提出Base理论。Base理论是对CAP理论的延伸,核心思想是:即使无法做到强一致性,但每个应用都可以根据自身业务特点,采用适当的方式来使系统达到最终一致性。
Base理论是对CAP理论中一致性和可用性权衡的结果,其来源于对大规模互联网系统分布式实践总结,是基于CAP理论逐步演化而来的,它大大降低了我们对系统的要求。
更加具体地说,Base理论是对CAP理论中AP方案的一个补充
核心概念
基本可用
基本可用是指分布式系统在出现不可预知故障的时候,允许损失部分可用性。这损失的部分功能可以是响应时间上的损失或非核心系统功能上的损失。
软状态
软状态指允许系统中数据存在中间状态,并认为该中间状态不会影响系统的整体可用性,即允许系统在不同节点的数据副本之间进行数据同步的过程存在延时。
最终一致性
最终一致性强调的是系统中所有的数据副本,在经过一段时间的同步后,最终能够达到一个一致的状态。因此,最终一致性的本质是需要系统保证最终数据能够达到一致,而不需要实时保证系统数据的强一致性。
在分布式系统中的一致性分为三种:
- 强一致性:系统写入了什么,读出来就是什么;
- 弱一致性:不一定可以读取到最新的值,也不保证多少时间之后读取到的数据是最新的,只是会尽量保证某个时刻达到数据一致的状态;
- 最终一致性:弱一致性的升级版,系统会保证在一定时间内达到数据一致的状态;
分布式事务的解决方案
基于上一节中的理论分析,可以看到分布式解决方案的两种目标:要么保证数据的一致性,要么保证数据的最终一致性。
二阶段提交协议(2PC)
二阶段提交协议(Two-Phase Commit,即2PC)是常用的分布式事务解决方案,它可以保证分布式事务中,要么所有参与进程都提交事务,要么都取消事务。因此二阶段提交协议它保证的数据的强一致性,要么所有服务同时修改某个数值,要么都不更改,以此来保证数据的强一致性。
在上面的分布式事务的例子中,其实最担心的就是在超时的状态下,订单服务无法感知到库存服务中事务的执行状态。因此在二阶段协议下,通过引入一个事务协调者来统一掌控所有节点的操作结果并最终指示这些节点是否要把操作结果进行真正的提交。
2PC将事务的提交分为两个阶段:Prepare阶段和Commit阶段
Prepare阶段
1️⃣协调者向参与者发送请求,询问当前事务能否处理成功;
2️⃣参与者开启本地事务执行数据库操作,但是并不会提交。根据操作结果,返回协调者执行的结果(返回yes表是可以提交,返回no表示不能提交)。
参与者在这一步需要准备好事务资源,记录undo、redo日志
Commit阶段
根据参与者返回的事务执行结果会有两种可能:
全部执行成功
1️⃣协调者向所有的参与者发送commit指定,要求所有的参与者提交本地事务;
2️⃣参与者接受到commit请求后,执行事务提交操作,并释放整个分布式事务期间占用的事务资源;
3️⃣参与者在执行完事务提交后,向协调者反馈事务的执行结果;
部分执行成功
1️⃣协调者向所有的参与者发送rollback指令,要求所有的参与者回滚本地事务;
2️⃣参与者接受到rollback请求后,执行事务的回滚操作,并释放整个分布式事务期间占用的事务资源;
3️⃣参与者在执行完事务提交后,向协调者反馈事务执行的结果;
2PC协议的缺点
2PC协议原理简单,实现起来很方便,但是也存在很多的问题。
同步阻塞
在二阶段的Commit阶段中,所有的节点都需要等待其它节点的响应,无法进行其它操作,这种同步阻塞极大的限制了分布式系统的性能。
单点问题
协调者在整个二阶段提交过程中很重要,如果协调者在提交阶段出现问题,那么整个流程将无法运转,更重要的是:其他参与者将会一直处于锁定事务资源的状态中,而无法继续完成事务操作。
数据不一致
假设协调者向参与和发送Commit请求之后,发生了局部网络异常或者是协调器在尚未发送完所有Commit请求之前自身发生了崩溃,导致最终只有部分参与者收到了Commit请求,这将导致严重的数据不一致。
过于保守
在二阶段提交的提交询问阶段中,参与者出现故障而导致协调者无法获取到所有参与者响应信息时,协调者只能依靠自身的超时机制来判断是否需要中断事务。简单来说,就是二阶段提交协议没有设计较为完善的容错机制,任意一个节点是失败都会导致整个事务的失败。
XA规范(2PC)
XA规范是由Open Group组织定义的分布式事务处理标准,旨在解决跨多个独立资源(如数据库、消息队列、文件系统)的事务一致性问题。其核心目标是为了不同厂商的资源管理系统RMS提供统一的接口规范,确保跨资源事务的原子性、一致性、隔离性和持久性。
XA规范的核心内容
角色定义
明确三个核心角色——应用程序(AP,发起事务的业务逻辑)、事务管理器(TM,协调全局事务的提交/回滚)、资源管理器(RM,管理本地资源,如数据库,执行本地事务并反馈状态)。
接口规范
定义了TM与RM之间的标准接口(如xa_start、xa_prepare、xa_commit、xa_rollback等),用于协调事务生命周期。
两阶段提交(2PC)
XA规范采用2PC作为其核心实现机制,通过“准备阶段(Prepare)”和“提交/回滚阶段(Commit/Rollback)”确保所有的RM要么全部提交事务,要么全部回滚。
XA规范与2PC提交协议的关系
2PC协议是一种通用的分布式事务提交协议,用于协调多个参与者的事务提交,而XA规范是2PC协议在资源管理器与事务管理器之间的具体实现标准。两者的关系可概括为:
- XA是2PC具体实现的框架:XA规范定义了TM与RM之间的接口,将2PC协议的“准备阶段”和“提交/回滚阶段”转化为可执行的标准化操作;
- 2PC是XA的核心实现机制:XA规范通过2PC协议解决跨资源事务的原子性问题 —— TM通过2PC的“准备阶段”收集所有RM的准备状态,再通过“提交/回滚阶段”统一指令,确保所有的RM的事务状态一直;
- XA扩展了2PC的功能:XA规范不仅包含2PC协议逻辑,还定义了资源管理器的注册、事务状态的回复等扩展功能,使得2PC协议更适合实际生产环境中的分布式事务处理。
XA规范的缺点
不适合高扩展的场景
XA规范要求每个参与者都支持XA协议,但是很多新一代的存储(如MongoDB、Redis、ElasticSearch等)或服务都不支持。
缺乏容错与最终一致性支持
XA规范是典型的ACID模型,追求强一致性,但不提供容错性强的最终一致性方案。在现代分布式系统中,更多采用BASE理论,而非强一致的ACID。
三阶段提交(3PC)协议
三阶段提交协议是二阶段提交协议的改进版本,三阶段提交有两个改动的点:
- 在协调者和参与者中都引入了超时机制
- 在第一阶段和第二阶段中插入一个准备阶段,保证了在最后提交阶段之前各个参与者的状态是一致的;
所以3PC提交协议分为了三个阶段:CanCommit准备阶段、PreCommit预提交阶段和DoCommit提交阶段。
阶段一:CanCommit阶段
协调者向参与者发送canCommit请求,参与者如果可以提交就返回YES响应,否则返回No响应,具体流程如下:
- 事务询问:协调者向所有参与者发出包含事务的canCommit请求,询问是否可以提交事务,并等待所有的事务参与者答复。
- 响应反馈:参与者收到canCommit请求后,如果认为可以执行事务操作,则反馈YES并进入预备状态,否则反馈NO;
阶段二:PreCommit阶段
假如所有参与者均反馈YES,协调者预执行事务,具体如下:
- 发送预提交请求:协调者向参与者发送PreCommit请求,并进入准备阶段;
- 事务预提交:参与者接收到PreCommit请求后,会执行本地事务,并将undo和redo信息记录到事务日志中(但不提交事务)
- 响应反馈:如果参与者成功的执行了事务操作,则返回ACK响应,同时开始等待最终指令;
假如有任何一个参与者协调者发送了NO响应,或者等待超时之后,协调都没有接到参与者响应,那么就执行事务的终端,流程如下:
- 发送中断请求:协调者向所有参与者发送abort请求
- 中断事务:参与者收到来自协调者的abort请求之后(或超时之后,仍未收到协调者的请求),执行事务的中断。
阶段三:doCommit阶段
该阶段进行真正的事务提交,也可以分为两种情况:
提交事务
- 发送提交请求:协调接受到所有参与者发送的ACK响应,那么它将从预提交状态进入到提交状态,并向所有参与者发送doCommit请求;
- 本地事务提交:参与者接受到doCommit请求之后,执行正式的事务提交,并在完成事务提交之后释放所有的事务资源;
- 响应反馈:事务提交完成之后,向协调者发送ACK响应;
- 完成事务:协调者接受到所有参与者的ack响应之后,完成事务;
中断事务
- 发送中断请求:如果协调者处于工作状态,向所有参与者发出abort请求;
- 事务回滚:参与者接受到abort请求之后,利用其在阶段二记录的undo信息来执行事务的回滚,并在完成回滚之后释放所有的事务资源;
- 反馈结果:参与者完成事务回滚之后,向协调者反馈ack消息;
- 中断事务:协调者接受到参与者反馈的ack消息之后,执行事务的中断;
3PC与2PC之间的区别
与2PC协议相比,3PC协议降低了阻塞范围,并且在等待超时之后,协调者或参与者会中断事务,避免了协调者单点问题。在阶段三中,协调者出现问题,参与者在等待一定的时间后仍然会继续提交事务。
在3PC协议中,进入doCommit阶段后,即使协调者出现了问题或者协调者与参与者之间的网络出现了问题,参与者仍然会在等待一段时间后提交事务。这个原因是,经历了前面两个阶段,说明了所有的参与者都有条件来执行的这个事务,所以直接执行是不会出现问题的。
3PC协议仍然无法解决数据不一致性的问题,如果参与者在接受到preCommit请求后等待doCommit指令时,如果此时协调者中断事务,而参与者因为网络故障无法接受到指令,会导致参与者继续提交事务,造成数据不一致的问题。
2PC和3PC协议都无法保证数据的绝对一致性,一般为了预防这个问题,可以添加报警,比如监控事务异常的时候,通过脚本自动补偿差异的信息