本地事务 vs 分布式事务:核心区别与解释

本地事务的基本概念

  • 本地事物,通常想到的,如ACID特性,通常在单个数据库中使用,由数据库本身来管理事务的提交和回滚

    • 数据库事务的几个特性:原子性(Atomicity)、一致性(Consistency)、隔离性或独立性(Isolation) 和持久性(Durabilily),简称就是 ACID。
    • 原子性: 一系列的操作整体不可拆分,要么同时成功,要么同时失败
    • 一致性: 数据在事务的前后,业务整体一致。
    • 隔离性: 事务之间互相隔离。
    • 持久性: 一旦事务成功,数据一定会落盘在数据库。
  • 分布式事务则涉及多个服务或数据库 ,需要跨网络协调,保证不同节点之间数据的一致性


本地事物在分布式下的问题

  • 远程服务假失败 :远程服务成功,由于网络故障没有返回。如锁库存假失败,由于网络原因连接超时,但是锁库存已经操作成功。此时,会导致订单数据回滚而库存数据没有回滚(即库存扣减)
  • SpringBoot事物的坑事物失效问题

Spring的事物哪些情况下会失效


为什么有分布式事物

  • 因为微服务架构中,各个服务之间互相调用难免会出现一些问题(尤其网络问题),那么如果没有实现分布式事务,就会出现数据一致性问题。

1. 定义范围与数据源

  • 本地事务(Local Transaction)
    范围 :在单个数据库单个资源管理器内完成。
    示例 :银行扣款操作仅操作自己的账户数据库 )。
    特点 :通过数据库的 ACID 特性(原子性、一致性、隔离性、持久性 )保证数据一致性。通过@Transactional注解管理单个数据库的ACID特性

  • 分布式事务(Distributed Transaction)
    范围 :跨多个数据库服务或资源管理器(如多个微服务、不同系统 )。
    示例 :跨行转账(操作A银行的账户扣款,同时操作B银行的账户加款)。
    特点 :需协调多个独立资源,解决网络延迟节点故障等问题。例如微服务架构中订单服务和库存服务需协同完成事务


2、实现机制与特性

  1. 原子性保障
  • 本地事务:数据库本身通过redo logundo log实现原子性,若操作失败直接回滚本地数据。
  • 分布式事务:依赖复杂协议(如两阶段提交2PC、补偿事务TCC)协调多个节点,例如Seata框架通过AT模式生成全局事物日志实现跨节点回滚。
  1. 一致性要求
  • 本地事务:通过数据库锁机制(如行锁、表锁)和隔离级别(如可重复读)保障单库内一致性。
  • 分布式事务:需解决网络延迟、节点故障等问题,可能需牺牲强一致性(CAP理论),采用最终一致性Base理论(基本可用、软状态)
  1. 协调机制
  • 本地事物:无协调器,直接由数据库自身管理事物生命周期。
  • 分布式事物:需引入事物协调器(如TM角色)管理全局事物状态,协调各参与者(RM角色)的提交或回滚。

3. 核心区别

对比维度 本地事务 分布式事务
原子性实现 数据库日志(undo/redo) 2PC、TCC、Saga等协议
数据位置 同一数据库实例 跨多个数据库、服务或系统
一致性模型 强一致性(ACID) 最终一致性或妥协一致性(BASE理论)
实现复杂度 简单(数据库内置支持) 复杂(需协调跨节点操作)
性能 高(无网络通信开销) 低(网络延迟、协调成本高)
容错性 高(单点故障风险低) 低(需处理网络分区、节点宕机等问题)
典型解决方案 数据库事务(如MySQL事务) 两阶段提交(2PC)、TCC、Saga、消息事务
应用场景 单服务库操作 跨服务、跨库的复杂操作

4、性能与复杂度

  1. 性能开销
  • 本地事务:无网络通讯协调成本执行效率高
  • 分布式事务:需多次跨节点通讯(如2PC的投票跟提交阶段),存在网络延迟资源锁定风险,性能显著下降
  1. 实现复杂度
  • 本地事务:实现简单,仅需数据库原生支持如SQL事物语句)。
  • 分布式事物:需处理网络分区、节点故障、消息重试等复杂场景,例如通过MQ实现最终一致性或通过TCC预留资源

5. 通俗比喻

  • 本地事务
    单人单任务

    你一个人在家做饭,从洗菜到炒菜全程自己控制,保证步骤连贯不出错。

  • 分布式事务
    多人协作项目

    团队分工:A买食材,B切菜,C炒菜。需要协调每个人是否完成自己的任务,如果有人掉链子(如A没买到菜),整个项目可能失败。


6. 分布式cap定理和BASE理论

cap定理
  • 指的是在一个分布式系统中,以下三种性质最多只能同时实现两点,不可能三者兼顾(CP/AP).
    • 一致性(Consistency): 分布式系统中的所有数据备份,在同一时刻是否同样的值等同于所有节点访问同一份最新的数据副本
    • 可用性(Availability): 集群部分节点故障后,集群整体是否还能享用客户端读写请求。(对数据更新具备高可用性
    • 分区容错性(Partition tolerance): 大多数分布式系统都分布在多个子网络。每个子网络就叫做一个区(partition)。分区容错的意思是:区间通信可能失败。比如:一台服务器放在中国,另一台服务器放在美国,这就是两个区,他们之间可能无法通信
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. 实际应用场景

  • 本地事务适用场景
    单体应用内的订单创建(同一数据库操作)、库存扣减

  • 分布式事务适用场景

    1. 跨行转账(不同银行系统
    2. 电商下单(订单服务扣库存、支付服务收款
    3. 微服务架构中跨服务数据更新(如用户注册后同步初始化多个子系统数据)

9. 常见分布式事务解决方案

方案 原理 适用场景
两阶段提交(2PC) 协调者统一指挥参与者提交或回滚 数据库跨库事务(如分库分表)
TCC模式 Try预占资源 → Confirm提交 → Cancel回滚 高一致性要求的金融交易
Saga模式 长事务拆分为多个子事务,失败时反向补偿 跨服务业务流程(如订单+物流)
消息事务 基于消息队列的最终一致性(如RocketMQ) 异步通知场景(如支付成功回调)

分布式事务深度解析:从理论到实践


总结

  • 本地事务 :简单高效,但仅限单一数据库
  • 分布式事务 :复杂但能解决跨系统协作问题,需权衡一致性与性能
  • 选择原则
    • 优先避免分布式事务(如设计单一职责服务);
    • 若无法避免,根据场景选择最终一致性或强一致性方案。
相关推荐
咖啡教室1 小时前
程序员应该掌握的网络命令telnet、ping和curl
运维·后端
你的人类朋友2 小时前
Let‘s Encrypt 免费获取 SSL、TLS 证书的原理
后端
老葱头蒸鸡2 小时前
(14)ASP.NET Core2.2 中的日志记录
后端·asp.net
失散132 小时前
分布式专题——23 Kafka日志索引详解
java·分布式·云原生·架构·kafka
程序消消乐2 小时前
深入理解Kafka的复制协议与可靠性保证
分布式·kafka
李昊哲小课3 小时前
Spring Boot 基础教程
java·大数据·spring boot·后端
码事漫谈3 小时前
C++内存越界的幽灵:为什么代码运行正常,free时却崩溃了?
后端
荣光波比3 小时前
ZooKeeper与Kafka分布式协调系统实战指南:从基础原理到集群部署
运维·分布式·zookeeper·kafka·云计算
Swift社区3 小时前
Spring Boot 3.x + Security + OpenFeign:如何避免内部服务调用被重复拦截?
java·spring boot·后端
90后的晨仔3 小时前
Mac 上配置多个 Gitee 账号的完整教程
前端·后端