如果你说:
Seata AT模式、TCC、Saga、XA...
你懂理论。
但如果问:
线上怎么做分布式事务?
那答案往往完全不一样。
先说结论
现在互联网Java项目里,真正大量使用的是:
第一梯队
✅ 最终一致性(消息队列)
本地事务 + MQ
例如:订单服务
↓
创建订单
↓
发送MQ
↓
库存服务扣库存
↓
积分服务加积分
↓
优惠券服务核销
阿里、京东、美团、字节大量业务都是这个思路。
第二梯队
✅ Seata AT
适合:
订单
库存
账户
多个数据库同时更新。
很多中小公司直接上。
第三梯队
✅ TCC
适合:
支付
转账
金融
要求极高一致性。
开发成本很高。
实际案例1:订单+库存
假设:
order-service
stock-service
用户下单:
java
createOrder()
同时:
java
deductStock()
很多新人写:
java
@Transactional
public void createOrder() {
orderMapper.insert();
stockFeign.deduct();
}
错。
因为:
@Transactional
只能管当前数据库
Feign调用根本不受控制。
生产最常见写法
订单服务:
java
@Transactional
public void createOrder(Order order){
orderMapper.insert(order);
kafkaTemplate.send(
"order_create",
order.getId()
);
}
保证:
订单成功
MQ一定发送
库存服务监听:
java
@KafkaListener(topics = "order_create")
public void consume(Long orderId){
stockMapper.deduct(orderId);
}
如果库存失败:
重试
补偿
人工介入
最终一致。
实际案例2:可靠消息最终一致性
这是目前最普遍方案。
订单库:
sql
order_info
再建:
sql
mq_message
业务事务:
java
@Transactional
public void createOrder(){
orderMapper.insert();
messageMapper.insert(
"ORDER_CREATE"
);
}
同一个事务。
提交成功:
订单有了
消息也有了
后台线程扫描:
java
@Scheduled
public void sendMessage(){
List<Message> list =
messageMapper.queryPending();
for(Message m:list){
kafka.send(m);
updateSuccess();
}
}
这就是:
事务消息
可靠消息
最终一致性
很多公司都这么干。
实际案例3:Seata
如果公司已经接入Seata。
代码反而简单。
订单服务:
java
@GlobalTransactional
public void createOrder(){
orderMapper.insert();
stockFeign.deduct();
accountFeign.reduce();
}
库存:
java
@Transactional
public void deduct(){
stockMapper.update();
}
账户:
java
@Transactional
public void reduce(){
accountMapper.update();
}
如果账户失败:
回滚订单
回滚库存
自动完成。
线上配置:
XML
seata:
enabled: true
再注册:
TC
TM
RM
即可。
为什么很多大厂不用Seata
因为:
性能
AT模式会生成:
undo_log
每次:
前镜像
后镜像
都要记录。
高并发压力大。
锁冲突
会有:
全局锁
例如:
库存1000
1万人抢。
容易卡。
所以:
高并发业务
=
MQ最终一致
更常见。
直接回答:
生产环境最常见的是基于MQ的最终一致性方案,例如Kafka、RocketMQ。业务先提交本地事务,再发送事务消息,由下游服务异步消费实现数据同步。对于强一致性要求不高的业务,这是主流方案。对于订单、库存、账户等需要强一致性的场景,中小公司常用Seata AT模式,大型金融场景会使用TCC。