分布式事务与最终一致性理论总结

本文深入探讨了分布式事务的概念,包括单数据源和多数据源事务的区别,以及常见的分布式事务解决方案。从二阶段提交(2PC)到三阶段提交(3PC)和TCC(Try-Confirm-Cancel)方案,分析了它们的优缺点。文章还介绍了事务状态表方案和基于消息中间件的最终一致性事务方案,强调了在网络环境中幂等性和最终一致性的关键作用。此外,讨论了最终一致性解决方案,如最大努力通知、TCC两阶段补偿以及基于可靠消息队列的方案,提供了理解分布式事务处理机制的全面视角。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

单数据源事务 & 多数据源事务

常见分布式事务解决方案

分布式事务模型

二将军问题和幂等性

两阶段提交(2PC)

三阶段提交(3PC)方案

TCC 方案

事务状态表方案

基于消息中间件的最终一致性事务方案

最终一致性

最大努力通知方案

TCC两阶段补偿方案

基于可靠性分布式消息队列

开源的分布式事务解决方案


注意:本文参考   1.4 w字,25 张图让你彻底掌握分布式事务原理

【分布式事务】最终一致性解决方案_A minor的博客-优快云博客_最终一致性的解决方案

单数据源事务 & 多数据源事务

如果一个应用程序在一次业务流中通过连接驱动和数据源接口只连接并查询(这里的查询是广义的,包括增删查改等)一个特定的数据库,该应用程序就可以利用数据库提供的事务机制(如果数据库支持事务的话)保证对库中记录所进行的操作的可靠性,这里的可靠性有四种语义:

原子性,A

一致性,C

隔离性,I

持久性,D

笔者在这里不再对这四种语义进行解释,了解单数据源事务及其 ACID 特性是读者阅读这篇文章的前提。单个数据库实现自身的事务特性是一个复杂又微妙的过程,例如 MySQL 的 InnoDB 引擎通过 Undo Log + Redo Log + ARIES 算法来实现。这是一个很宏大的话题,不在本文的描述范围,读者有兴趣的话可自行研究。

单数据源事务也可以叫做单机事务,或者本地事务。

在分布式场景下,一个系统由多个子系统构成,每个子系统有独立的数据源。多个子系统之间通过互相调用来组合出更复杂的业务。在时下流行的微服务系统架构中,每一个子系统被称作一个微服务,同样每个微服务都维护自己的数据库,以保持独立性。

例如,一个电商系统可能由购物微服务、库存微服务、订单微服务等组成。购物微服务通过调用库存微服务和订单微服务来整合出购物业务。用户请求购物微服务商完成下单时,购物微服务一方面调用库存微服务扣减相应商品的库存数量,另一方面调用订单微服务插入订单记录(为了后文描述分布式事务解决方案的方便,这里给出的是一个最简单的电商系统微服务划分和最简单的购物业务流程,后续的支付、物流等业务不在考虑范围内)。电商系统模型如下图所示:

在用户购物的业务场景中,shopping-service 的业务涉及两个数据库:库存库(repo_db)和订单库(repo_db),也就是 g 购物业务是调用多数据源来组合而成的。作为一个面向消费者的系统,电商系统要保证购物业务的高度可靠性,这里的可靠性同样有 ACID 四种语义。

但是一个数据库的本地事务机制仅仅对落到自己身上的查询操作(这里的查询是广义的,包括增删改查等)起作用,无法干涉对其他数据库的查询操作。所以,数据库自身提供的本地事务机制无法确保业务对多数据源全局操作的可靠性。

基于此,针对多数据源操作提出的分布式事务机制就出现了。

分布式事务也可以叫做全局事务。

常见分布式事务解决方案

分布式事务模型

描述分布式事务,常常会使用以下几个名词:

事务参与者:例如每个数据库就是一个事务参与者

事务协调者:访问多个数据源的服务程序,例如 shopping-service 就是事务协调者

资源管理器(Resource Manager, RM):通常与事务参与者同义

事务管理器(Transaction Manager, TM):通常与事务协调者同义

在分布式事务模型中,一个 TM 管理多个 RM,即一个服务程序访问多个数据源;TM 是一个全局事务管理器,协调多方本地事务的进度,使其共同提交或回滚,最终达成一种全局的 ACID 特性。

二将军问题和幂等性

二将军问题是网络领域的一个经典问题,用于表达计算机网络中互联协议设计的微妙性和复杂性。这里给出一个二将军问题的简化版本:

一支白军被围困在一个山谷中,山谷的左右两侧是蓝军。困在山谷中的白军人数多于山谷两侧的任意一支蓝军,而少于两支蓝军的之和。若一支蓝军对白军单独发起进攻,则必败无疑;但若两支蓝军同时发起进攻,则可取胜。两只蓝军的总指挥位于山谷左侧,他希望两支蓝军同时发起进攻,这样就要把命令传到山谷右侧的蓝军,以告知发起进攻的具体时间。假设他们只能派遣士兵穿越白军所在的山谷(唯一的通信信道)来传递消息,那么在穿越山谷时,士兵有可能被俘虏。

只有当送信士兵成功往返后,总指挥才能确认这场战争的胜利(上方图)。现在问题来了,派遣出去送信的士兵没有回来,则左侧蓝军中的总指挥能不能决定按命令中约定的时间发起进攻?

答案是不确定,派遣出去送信的士兵没有回来,他可能遇到两种状况:

1)命令还没送达就被俘虏了(中间图),这时候右侧蓝军根本不知道要何时进攻;

2)命令送达,但返回途中被俘虏了(下方图),这时候右侧蓝军知道要何时进攻,但左侧蓝军不知道右侧蓝军是否知晓进攻时间。

类似的问题在计算机网络中普遍存在,例如发送者给接受者发送一个 HTTP 请求,或者 MySQL 客户端向 MySQL 服务器发送一条插入语句,然后超时了没有得到响应。请问服务器是写入成功了还是失败了?答案是不确定,有以下几种情况:

1)可能请求由于网络故障根本没有送到服务器,因此写入失败;

2)可能服务器收到了,也写入成功了,但是向客户端发送响应前服务器宕机了;

3)可能服务器收到了,也写入成功了,也向客户端发送了响应,但是由于网络故障未送到客户端。

无论哪种场景,在客户端看来都是一样的结果:它发出的请求没有得到响应。为了确保服务端成功写入数据,客户端只能重发请求,直至接收到服务端的响应。

类似的问题问题被称为网络二将军问题。

网络二将军问题的存在使得消息的发送者往往要重复发送消息,直到收到接收者的确认才认为发送成功,但这往往又会导致消息的重复发送。例如电商系统中订单模块调用支付模块扣款的时候,如果网络故障导致二将军问题出现,扣款请求重复发送,产生的重复扣款结果显然是不能被接受的。因此要保证一次事务中的扣款请求无论被发送多少次,接收方有且只执行一次扣款动作,这种保证机制叫做接收方的幂等性。

两阶段提交(2PC)

2PC 是一种实现分布式事务的简单模型,这两个阶段是:

1)准备阶段:事务协调者向各个事务参与者发起询问请求:“我要执行全局事务了,这个事务涉及到的资源分布在你们这些数据源中,分别是……,你们准备好各自的资源(即各自执行本地事务到待提交阶段)”。各个参与者协调者回复 yes(表示已准备好,允许提交全局事务)或 no(表示本参与者无法拿到全局事务所需的本地资源,因为它被其他本地事务锁住了)或超时。

1阶段阶段一:提交事务请求

事务询问

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值