1. 为什么数据一致性如此重要?
在分布式系统和微服务架构盛行的今天,数据一致性已经成为系统设计中不可忽视的核心问题。想象一下电商系统中的库存扣减和订单创建,如果这两个操作不能保持原子性,就可能出现超卖或者订单创建失败但库存已扣的尴尬情况。
Spring Boot作为Java生态中最流行的应用框架,其事务管理机制直接关系到业务数据的准确性。我曾参与过一个支付系统重构项目,就因为在事务边界划分上的疏忽,导致出现了金额对不齐的问题,排查起来异常痛苦。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. Spring事务管理基础
2.1 声明式事务的本质
Spring的@Transactional注解实际上是通过AOP实现的代理模式。当你在方法上添加这个注解时,Spring会在运行时创建一个代理对象,在方法调用前后加入事务管理的逻辑。这包括:
- 获取数据库连接
- 设置事务隔离级别
- 开启事务
- 执行业务逻辑
- 根据执行结果提交或回滚
java复制@Service
public class OrderService {
@Transactional
public void createOrder(OrderDTO dto) {
// 业务逻辑
}
}
2.2 事务传播行为的7种模式
传播行为决定了事务方法被另一个事务方法调用时,事务应该如何传播。这是最容易踩坑的地方:
- REQUIRED(默认):如果当前存在事务,就加入该事务;如果当前没有事务,就新建一个事务
- REQUIRES_NEW:新建事务,如果当前存在事务,把当前事务挂起
- NESTED:如果当前存在事务,则在嵌套事务内执行;如果当前没有事务,则新建事务
- SUPPORTS:如果当前存在事务,就加入该事务;如果当前没有事务,就以非事务方式执行
- NOT_SUPPORTED:以非事务方式执行,如果当前存在事务,就把当前事务挂起
- NEVER:以非事务方式执行,如果当前存在事务,就抛出异常
- MANDATORY:如果当前存在事务,就加入该事务;如果当前没有事务,就抛出异常
提示:REQUIRES_NEW和NESTED的区别在于,REQUIRES_NEW会完全独立于外部事务,而NESTED是外部事务的子事务,外部事务回滚会导致嵌套事务回滚,但嵌套事务可以单独回滚不影响外部事务。
3. 分布式事务解决方案
3.1 本地消息表方案
这是最经典的最终一致性方案,适合对实时性要求不高的场景:
- 在业务数据库中创建消息表
- 业务操作和消息记录在同一个本地事务中完成
- 后台任务定期扫描消息表,将未处理的消息发送到MQ
- 消费方处理消息并更新状态
sql复制CREATE TABLE transaction_message (
id BIGINT PRIMARY KEY,
biz_id VARC
