分布式事务介绍一下
【问】分布式事务介绍一下
分布式事务,典型场景:当一次业务操作需要同时更新多个不同的数据库或系统时,如何保证全部成功,或全部失败回滚。
- 创建订单 → 扣减库存 → 扣减用户余额
- 三个操作分别在不同服务、不同数据库中执行
- 数据库 + 消息队列
- 更新订单状态 → 发送“支付成功”消息到 Kafka/RocketMQ
- 要求:要么都成功,要么都不发生(避免消息丢失或重复消费)
- 如果没有分布式事务,可能出现:
- 订单创建成功,但库存没扣 → 超卖
- 扣了钱但订单失败 → 用户资金损失
- 消息没发出去 → 下游业务卡住
CAP 权衡: 强一致性(C)往往牺牲可用性(A)或分区容忍性(P)
事务消息 —— 最终一致性(目前互联网公司最常用的方案!)
- 核心思想:利用“本地事务 + 消息队列”实现可靠事件通知
- 步骤(以 RocketMQ 事务消息为例):
- 发送“半消息”到 MQ(不可被消费)--小明先对邮递员说:“我要发一封信给小红,但你先别送,等我准备好!”
- 执行本地 DB 操作(如更新订单)--然后他去拿10块钱
- 根据 DB 结果,提交或回滚半消息 --若拿到钱则对邮递员说:“现在可以把信给小红了!”;若没有则“别送了,取消!”
- 消费者收到消息后执行下游操作(如扣库存)--不能立刻让小红知道,但最终一定会让她知道,并且钱也不会丢——这就叫 “最终一致性”
- RabbitMQ 没有半消息;若需事务消息能力,建议用
本地消息表+RabbitMQ,或改用 RocketMQ(原生支持)。
优点:
- 实现简单,性能高
- 天然支持最终一致性
框架支持:
- RocketMQ(原生支持事务消息)
- Kafka(需配合本地消息表)
- Seata AT 模式(基于 undo log)
本地消息表
- 本地消息表是一种实现最终一致性的简单可靠方法。
- 它的核心思想是:把“业务操作”和“发消息”放在同一个数据库事务中完成。比如下单时,先在订单表插入数据,同时在一张专门的“消息表”里写一条待发送的消息,两者一起提交。如果成功,后续由后台任务读取消息表,把消息发给其他服务(如扣库存);如果失败,整个事务回滚,消息也不会残留。这样即使系统崩溃,也能通过重试保证消息最终被处理,避免数据不一致。
下单 → 订单表 + 消息表(待发送的消息), 同时插入—成功→ 后台任务读消息表 → 扣库存
↪失败→ 整个事务回滚
XA 协议(2PC / 两阶段提交) —— 强一致性
- 原理:由事务管理器(TM)协调多个资源管理器(RM,如数据库)
- 阶段1(Prepare):TM 问所有 RM:“能提交吗?” → RM 锁资源并预写日志
- 阶段2(Commit/Rollback):若全部同意,则提交;否则回滚
浙公网安备 33010602011771号