分布式事务面试题
Q1:分布式事务具体指的是什么意思?
答:
分布式事务是指在分布式系统中,一个业务操作需要跨越多个服务(微服务)或多个数据库节点,这些操作要么全部成功、要么全部回滚,以保证数据的一致性。
举例:
- 用户下单:订单服务插入订单记录 + 库存服务扣减库存 + 积分服务增加积分
- 这三步操作分布在三个不同的微服务/数据库中
- 如果扣减库存成功、积分失败,就会出现数据不一致问题
- 分布式事务要保证这三个操作要么全成功,要么全回滚
Q2:项目中分布式事务用在哪个地方?
答:
常见场景举例(结合实际项目作答):
- 电商下单场景:下单时需要同时操作订单服务(创建订单)、库存服务(扣减库存)、账户服务(扣款),三个服务各自独立数据库,需用分布式事务保证一致性。
- 支付场景:支付服务和账单服务之间的余额扣减与账单生成必须保持原子性。
- 物流场景:创建物流单与更新订单状态必须同时成功或同时失败。
面试时结合自己项目中的真实业务描述,说清楚"哪两个(或多个)服务之间需要保证事务一致性"即可。
Q3:CAP 定理知道吗,是什么意思?
答:
CAP 定理是分布式系统中的核心理论,指出分布式系统无法同时满足以下三个特性,最多只能同时满足其中两个:
| 字母 | 英文 | 含义 |
|---|---|---|
| C | Consistency(一致性) | 所有节点在同一时刻访问到的数据是一致的 |
| A | Availability(可用性) | 每次请求都能收到响应(不保证是最新数据) |
| P | Partition Tolerance(分区容错性) | 系统在网络分区(部分节点通信故障)时仍能正常运行 |
实际选择:
- 分布式系统中网络分区(P)是必然存在的,所以 P 必须保证
- 因此实际是在 CP 和 AP 之间做权衡:
- CP(强一致性):如 ZooKeeper、HBase,牺牲可用性保一致性
- AP(高可用性):如 Eureka、Cassandra,牺牲强一致性保可用性
Q4:Seata 的模式有几种,你用的哪个?
答:
Seata 目前支持以下 4 种事务模式:
| 模式 | 全称 | 特点 |
|---|---|---|
| AT 模式 | Automatic Transaction | 自动补偿,无侵入,最常用 |
| TCC 模式 | Try-Confirm-Cancel | 手动编写三段逻辑,控制灵活,侵入性高 |
| SAGA 模式 | 长事务模式 | 适合长链路事务,通过补偿机制实现 |
| XA 模式 | 基于数据库 XA 协议 | 强一致性,性能较差 |
项目中一般用 AT 模式(Seata 默认模式),因为:
- 无需修改业务代码,侵入性低
- 自动生成 undo_log,支持自动回滚
- 适合大多数常规业务场景
Q5:Seata 的注解你们用的是哪一个?
答:
项目中使用 @GlobalTransactional 注解。
@GlobalTransactional
public void createOrder(OrderDTO orderDTO) {
// 创建订单
orderService.create(orderDTO);
// 扣减库存
stockService.deduct(orderDTO.getProductId(), orderDTO.getCount());
// 扣减账户余额
accountService.deduct(orderDTO.getUserId(), orderDTO.getMoney());
}
- 加在事务发起方(TM)的业务方法上
- 标注后 Seata 会自动开启全局事务,管理整个分布式事务的提交与回滚
- 其他参与者(RM)不需要加注解,只需引入 Seata 依赖并配置数据源代理即可
Q6:AT 模式的工作原理讲下?
答:
AT 模式基于**两阶段提交(2PC)**实现,但做了自动化处理:
第一阶段(执行阶段):
- 业务 SQL 执行前,Seata 拦截 SQL,查询并保存执行前的数据快照(before image)
- 执行业务 SQL
- 查询并保存执行后的数据快照(after image)
- 将前后镜像数据写入 undo_log 表
- 提交本地事务(此时数据已实际写入,undo_log 也已记录)
第二阶段(提交/回滚):
- 全局提交:删除 undo_log 记录即可(数据已真实提交)
- 全局回滚:读取 undo_log 中的 before image,生成反向 SQL,恢复数据,再删除 undo_log
关键组件:
- TC(Transaction Coordinator):事务协调器,运行在 Seata Server,负责全局事务的提交/回滚决策
- TM(Transaction Manager):事务管理器,事务发起方,负责开启、提交、回滚全局事务
- RM(Resource Manager):资源管理器,事务参与方,负责分支事务的注册和执行
Q7:Seata 的重要角色有几个?
答:
Seata 有 3 个核心角色:
| 角色 | 全称 | 职责 |
|---|---|---|
| TC | Transaction Coordinator(事务协调器) | 部署在 Seata Server,维护全局事务状态,负责协调各分支事务的提交或回滚 |
| TM | Transaction Manager(事务管理器) | 集成在业务应用中,负责开启、提交、回滚全局事务(即加了 @GlobalTransactional 的那个服务) |
| RM | Resource Manager(资源管理器) | 集成在各个参与事务的微服务中,负责管理本地资源(数据库),向 TC 注册分支事务并汇报状态 |
交互流程:
- TM 向 TC 申请开启全局事务,获取 XID
- 各 RM 执行本地事务,注册分支事务到 TC
- TM 根据执行情况向 TC 发起全局提交或回滚
- TC 通知所有 RM 执行对应的提交或回滚操作
Q8:假设不用 Seata,还有其他方案可以保证分布式事务一致性吗?
答:
有,以下是几种常见的替代方案:
1. 本地消息表(Local Message Table)
- 在业务数据库中创建一张消息表
- 业务操作和写消息表在同一本地事务中完成
- 通过定时任务将消息发给下游服务,下游消费成功后删除消息
- 优点:实现简单,可靠性高;缺点:与业务耦合,增加数据库压力
2. 可靠消息最终一致性(MQ 事务消息)
- 利用 RocketMQ 的事务消息机制
- 发送半消息 → 执行本地事务 → 提交/回滚消息
- 消费者消费消息,保证最终一致性
- 适合场景:对实时一致性要求不高,允许短暂不一致
3. TCC 模式(Try-Confirm-Cancel)
- 业务层面手动实现三个接口:
- Try:预留资源(如冻结库存)
- Confirm:确认提交(如正式扣减)
- Cancel:释放资源(如解冻库存)
- 优点:性能好,不依赖数据库锁;缺点:代码侵入性强,需幂等设计
4. SAGA 模式
- 将长事务拆分为多个本地事务,每步都有对应的补偿操作
- 正向成功则提交,某步失败则逆向补偿
- 适合:长链路、步骤多的业务场景
5. 最大努力通知
- 发送通知后,不管对方是否接收成功,只做有限次重试
- 适合对一致性要求较低的场景,如发短信通知、发票推送等
总结:分布式事务没有银弹,需要根据业务对一致性要求和性能要求的权衡来选择合适方案。Seata AT 模式适合强一致性要求场景;MQ 事务消息适合最终一致性场景;TCC 适合高并发、强控制需求场景。