本地事务的基本概念
-
本地事物,通常想到的,如
ACID特性
,通常在单个数据库
中使用,由数据库本身来管理事务的提交和回滚。- 数据库事务的几个特性:原子性(Atomicity)、一致性(Consistency)、隔离性或独立性(Isolation) 和持久性(Durabilily),简称就是 ACID。
- 原子性: 一系列的操作整体不可拆分,要么同时成功,要么同时失败
- 一致性: 数据在事务的前后,业务整体一致。
- 隔离性: 事务之间互相隔离。
- 持久性: 一旦事务成功,数据一定会落盘在数据库。
-
分布式事务则涉及多个服务或数据库 ,需要
跨网络协调
,保证不同节点之间数据的一致性
。
本地事物在分布式下的问题
- 远程服务假失败 :远程服务成功,由于网络故障没有返回。如
锁库存假失败
,由于网络原因连接超时,但是锁库存已经操作成功。此时,会导致订单数据回滚而库存数据没有回滚(即库存扣减)
。 - SpringBoot事物的坑 (
事物失效问题
)
为什么有分布式事物
- 因为
微服务架构
中,各个服务之间互相调用
难免会出现一些问题(尤其网络问题
),那么如果没有实现分布式事务,就会出现数据一致性
问题。
1. 定义范围与数据源
-
本地事务(Local Transaction)
范围 :在单个数据库
或单个资源管理器
内完成。
示例 :银行扣款操作
(仅操作自己的账户数据库 )。
特点 :通过数据库的ACID
特性(原子性、一致性、隔离性、持久性 )保证数据一致性
。通过@Transactional
注解管理单个数据库的ACID特性 -
分布式事务(Distributed Transaction)
范围 :跨多个数据库
、服务或资源管理器
(如多个微服务、不同系统 )。
示例 :跨行转账(操作A银行的账户扣款
,同时操作B银行的账户加款
)。
特点 :需协调多个独立资源
,解决网络延迟
、节点故障
等问题。例如微服务架构中订单服务和库存服务需协同完成事务
2、实现机制与特性
- 原子性保障
- 本地事务:数据库本身通过
redo log
和undo log
实现原子性,若操作失败直接回滚本地数据。 - 分布式事务:依赖复杂协议(如
两阶段提交2PC、补偿事务TCC
)协调多个节点,例如Seata框架通过AT模式生成全局事物日志实现跨节点回滚。
- 一致性要求
- 本地事务:通过数据库锁机制(如
行锁、表锁
)和隔离级别(如可重复读
)保障单库内一致性。 - 分布式事务:需解决
网络延迟、节点故障
等问题,可能需牺牲强一致性(CAP理论)
,采用最终一致性
或Base理论(基本可用、软状态)
。
- 协调机制
- 本地事物:
无协调器
,直接由数据库自身管理事物生命周期。 - 分布式事物:需引入
事物协调器(如TM角色)
管理全局事物状态,协调各参与者(RM角色)
的提交或回滚。
3. 核心区别
对比维度 | 本地事务 | 分布式事务 |
---|---|---|
原子性实现 | 数据库日志(undo/redo) | 2PC、TCC、Saga等协议 |
数据位置 | 同一数据库实例 | 跨多个数据库、服务或系统 |
一致性模型 | 强一致性(ACID) | 最终一致性或妥协一致性(BASE理论) |
实现复杂度 | 简单(数据库内置支持) | 复杂(需协调跨节点操作) |
性能 | 高(无网络通信开销) | 低(网络延迟、协调成本高) |
容错性 | 高(单点故障风险低) | 低(需处理网络分区、节点宕机等问题) |
典型解决方案 | 数据库事务(如MySQL事务) | 两阶段提交(2PC)、TCC、Saga、消息事务 |
应用场景 | 单服务库操作 | 跨服务、跨库的复杂操作 |
4、性能与复杂度
- 性能开销
- 本地事务:无
网络通讯
和协调成本
,执行效率高。 - 分布式事务:需
多次跨节点通讯(如2PC的投票跟提交阶段)
,存在网络延迟
跟资源锁定
风险,性能显著下降。
- 实现复杂度
- 本地事务:实现简单,仅需数据库原生支持 (
如SQL事物语句
)。 - 分布式事物:需处理
网络分区、节点故障、消息重试等
复杂场景,例如通过MQ实现最终一致性
或通过TCC预留资源
。
5. 通俗比喻
-
本地事务 :
单人单任务你一个人在家做饭,从
洗菜到炒菜全程自己控制
,保证步骤连贯不出错。 -
分布式事务 :
多人协作项目团队分工:
A买食材,B切菜,C炒菜
。需要协调每个人是否完成自己的任务,如果有人掉链子(如A没买到菜),整个项目可能失败。
6. 分布式cap定理和BASE理论
cap定理
- 指的是在一个分布式系统中,以下三种性质最多只能同时实现两点,不可能三者兼顾(CP/AP).
- 一致性(Consistency):
分布式系统
中的所有数据备份
,在同一时刻
是否同样的值
(等同于所有节点访问同一份最新的数据副本
) - 可用性(Availability):
集群
一部分节点故障
后,集群整体
是否还能享用客户端读写请求
。(对数据更新具备高可用性) - 分区容错性(Partition tolerance): 大多数分布式系统都分布在多个子网络。每个子网络就叫做一个区(partition)。分区容错的意思是:
区间通信
可能失败。比如:一台服务器放在中国,另一台服务器放在美国,这就是两个区,他们之间可能无法通信。
- 一致性(Consistency):
CP面临的问题
- 多数大型互联网应用场景,主机众多、部署分散,集群规模大。所以
节点故障、网络故障
是常态。要保证服务可用性达到 99.99999%(N 个 9) ,即保证 P 和 A
,舍弃 C
。
BASE理论
-
对 CAP 理论的延伸 ,思想是
即使无法做到强一致性
(CAP 的一致性就是强一致性),但可以适当的采取弱一致性
即最终一致性。 -
基本可用(Basically Available):
-
指
分布式系统
在出现故障
的时候,允许损失部分可用性
(例如:响应时间、功能上的可用性)。需要注意的是,基本可用绝不等价于系统不可用。 -
响应时间上的损失 :正常情况下
搜索引擎需要在0.5秒之内返回给用户相应的查询结果
,但由于出现故障(比如系统部分机房发生断电或断网故障),查询结果的响应时间增加到了 1~2秒。 -
功能上的损失:购物网站在购物高峰(如双十一时),为了保护系统的稳定性,部分消费者可能会被引导到一个降级页面。
-
-
软状态(Soft State):
- 软状态是指允许系统存在中间状态,而该中间状态不会影响系统整体可用性。分布式存储中一般一份数据会有多个副本,允许不同副本同步的延时就是软状态的体现。mysql replication 的异步复制也是一种体现。
-
最终一致性(Nventual Consistency):
- 最终一致性是指系统中的所有数据副本经过一定时间后 ,
最终能够达到一致
的状态。弱一致性和强一致性
相反,最终一致性是弱一致性的一种特殊情况。
- 最终一致性是指系统中的所有数据副本经过一定时间后 ,
7. 代码示例对比
本地事务(MySQL)
java
// 使用Spring的@Transactional注解管理单个数据库事务
@Transactional
public void transferLocal(int fromUserId, int toUserId, BigDecimal amount) {
// 扣减转出账户余额
accountDao.deduct(fromUserId, amount);
// 增加转入账户余额(同一数据库)
accountDao.add(toUserId, amount);
}
分布式事务(TCC模式)
java
// 跨服务转账(TCC模式:Try-Confirm-Cancel)
public void transferDistributed(int fromUserId, int toUserId, BigDecimal amount) {
// 1. Try阶段:预锁定资源
boolean tryResult = bankATryService.deduct(fromUserId, amount); // 调用银行A的预扣款接口
boolean tryResult2 = bankBTryService.add(toUserId, amount); // 调用银行B的预收款接口
if (tryResult && tryResult2) {
// 2. Confirm阶段:提交事务
bankAConfirmService.commit(fromUserId, amount); // 银行A实际扣款
bankBConfirmService.commit(toUserId, amount); // 银行B实际收款
} else {
// 3. Cancel阶段:回滚事务
bankACancelService.rollback(fromUserId, amount);
bankBCancelService.rollback(toUserId, amount);
}
}
8. 实际应用场景
-
本地事务适用场景 :
单体应用
内的订单创建
(同一数据库操作)、库存扣减
。 -
分布式事务适用场景:
- 跨行转账(
不同银行系统
) - 电商下单(
订单服务扣库存、支付服务收款
) - 微服务架构中跨服务数据更新(如用户注册后同步初始化多个子系统数据)
- 跨行转账(
9. 常见分布式事务解决方案
方案 | 原理 | 适用场景 |
---|---|---|
两阶段提交(2PC) | 协调者统一指挥参与者提交或回滚 | 数据库跨库事务(如分库分表) |
TCC模式 | Try预占资源 → Confirm提交 → Cancel回滚 | 高一致性要求的金融交易 |
Saga模式 | 长事务拆分为多个子事务,失败时反向补偿 | 跨服务业务流程(如订单+物流) |
消息事务 | 基于消息队列的最终一致性(如RocketMQ) | 异步通知场景(如支付成功回调) |
总结
- 本地事务 :简单高效,但仅限
单一数据库
。 - 分布式事务 :复杂但能解决
跨系统协作
问题,需权衡一致性与性能
。 - 选择原则 :
- 优先避免分布式事务(如设计单一职责服务);
- 若无法避免,根据场景选择最终一致性或强一致性方案。