亿级分布式系统架构演进实战(十)- 垂直拆分(分布式事务管理设计)

亿级分布式系统架构演进实战(一)- 总体概要
亿级分布式系统架构演进实战(二)- 横向扩展(服务无状态化)
亿级分布式系统架构演进实战(三)- 横向扩展(数据库读写分离)
亿级分布式系统架构演进实战(四)- 横向扩展(负载均衡与弹性伸缩)
亿级分布式系统架构演进实战(五)- 横向扩展(缓存策略设计)
亿级分布式系统架构演进实战(六)- 横向扩展(监控与日志体系)
亿级分布式系统架构演进实战(七)- 横向扩展(安全防护设计)
亿级分布式系统架构演进实战(八)- 垂直拆分(领域划分及垂直分库设计)
亿级分布式系统架构演进实战(九)- 垂直拆分(服务间通信设计)

一、核心目标

解决跨服务数据一致性问题,平衡性能与一致性

  1. 强一致性:确保跨服务操作原子性,适用于金融等高敏感场景。
  2. 最终一致性:通过异步补偿机制,提升系统吞吐量和可用性。
  3. 可观测性:全链路监控事务状态,支持人工介入异常处理。

二、强一致性方案

1. Seata AT模式(自动补偿)

设计意图

简化开发 :通过全局锁机制自动回滚事务,减少业务侵入。

适用场景:电商订单创建(扣库存+生成订单)。

技术实现

全局事务ID(XID) :Seata客户端生成唯一ID,贯穿所有子事务。

数据快照:记录事务前后的数据镜像,用于自动回滚。

生产配置示例

yaml 复制代码
# Seata Server配置(Nacos注册中心)
seata:
  registry:
    type: nacos
    nacos:
      server-addr: 127.0.0.1:8848
  config:
    type: nacos
    nacos:
      server-addr: 127.0.0.1:8848

优劣势

优势 :开发简单,适合传统事务迁移场景。

劣势:全局锁可能导致性能瓶颈(建议分库分表优化)。


2. XA两阶段提交(数据库原生支持)

设计意图

强一致性保障:数据库原生支持,适合金融转账等高敏感场景。

技术实现

Phase 1(Prepare) :所有参与者锁定资源,返回准备状态。

Phase 2(Commit/Rollback):协调者根据Prepare结果提交或回滚。

代码示例

java 复制代码
// MySQL XA事务示例
XADataSource xaDataSource = ... // 获取XA数据源
XAResource xaRes = xaDataSource.getXAConnection().getXAResource();
Xid xid = new MyXid(); // 全局事务ID

try {
    xaRes.start(xid, XAResource.TMNOFLAGS);
    // 执行SQL操作(如扣款)
    xaRes.end(xid, XAResource.TMSUCCESS);
    xaRes.prepare(xid);
    xaRes.commit(xid, false); // 提交事务
} catch (XAException e) {
    xaRes.rollback(xid); // 回滚事务
}

优劣势

优势 :严格ACID,适合银行核心系统。

劣势:同步阻塞,性能较低(TPS < 500)。


3. TCC模式(手动补偿)

设计意图

灵活控制:通过Try-Confirm-Cancel三阶段,支持自定义补偿逻辑。

技术实现

Try :预留资源(如冻结库存)。

Confirm :提交事务(如确认扣减库存)。

Cancel:回滚预留(如解冻库存)。

代码示例

java 复制代码
public interface InventoryTccService {
    @TwoPhaseBusinessAction(name = "prepare", commitMethod = "confirm", rollbackMethod = "cancel")
    boolean prepare(BusinessActionContext context, @BusinessActionContextParameter(paramName = "skuId") String skuId, int count);
    
    boolean confirm(BusinessActionContext context);
    boolean cancel(BusinessActionContext context);
}

生产配置

幂等性保障 :通过唯一事务ID避免重复提交。

超时控制:设置Try阶段最长等待时间(如30秒)。

优劣势

优势 :高性能,适合秒杀等高并发场景。

劣势:开发复杂,需手动实现补偿逻辑。


三、最终一致性方案

1. Saga模式(正向+逆向补偿)

设计意图

长事务处理:通过事件驱动逐步执行事务,失败时逆向补偿。

技术实现

正向操作 :依次执行子事务(如创建订单 → 扣库存)。

补偿操作:逆向回滚(如取消订单 → 返还库存)。

代码示例

java 复制代码
// Saga流程定义(使用Apache Camel)
from("direct:createOrder")
    .saga()
    .compensation("direct:cancelOrder")
    .to("bean:orderService?method=createOrder")
    .to("bean:inventoryService?method=deductStock");

from("direct:cancelOrder")
    .to("bean:orderService?method=cancelOrder")
    .to("bean:inventoryService?method=restoreStock");

优劣势

优势 :支持复杂业务流程,适合电商订单。

劣势:补偿逻辑需覆盖所有失败场景。


2. 异步校对(定时补偿)

设计意图

数据最终一致:通过定时任务检测并修复不一致状态。

技术实现

定时任务 :扫描事务表,检查未完成的事务。

补偿触发:对异常事务执行修复(如重试或回滚)。

生产配置示例

sql 复制代码
-- 检测未完成订单
SELECT order_id 
FROM orders 
WHERE status = 'CREATED' 
  AND create_time < NOW() - INTERVAL '10 minutes';

优劣势

优势 :实现简单,适合对一致性要求不高的场景(如日志记录)。

劣势:修复延迟,可能影响用户体验。


3. 事务消息(RocketMQ)

设计意图

可靠消息投递:确保本地事务与消息发送的原子性。

技术实现

半消息 :消息暂存Broker,不可被消费。

事务状态回查:Broker定期检查生产者事务状态。

代码示例

java 复制代码
// 发送事务消息
TransactionSendResult result = producer.sendMessageInTransaction(message, order);
if (result.getLocalTransactionState() == LocalTransactionState.ROLLBACK_MESSAGE) {
    // 事务回滚处理
}

// 消费端幂等处理
if (redis.setnx(orderId, "PROCESSING") == 1) {
    inventoryService.deductStock(orderId);
}

优劣势

优势 :高吞吐量(TPS > 10k),适合订单创建场景。

劣势:依赖消息队列可用性。


4. 本地事务消息表

设计意图

去中心化事务:通过本地事务保证业务操作与消息写入的原子性。

技术实现

  1. 业务表与消息表在同一个事务中写入。
  2. 定时任务扫描消息表,发送消息到MQ。

数据库表设计

sql 复制代码
CREATE TABLE transaction_messages (
    id BIGINT PRIMARY KEY,
    topic VARCHAR(100),
    payload TEXT,
    status ENUM('PENDING', 'SENT'),
    created_time TIMESTAMP
);

优劣势

优势 :不依赖MQ事务消息功能,兼容性高。

劣势:需额外维护消息表,增加数据库压力。


5. Transactional Outbox

设计意图

可靠事件发布:通过数据库事务确保事件持久化,外部消费者轮询获取。

技术实现

  1. 业务操作与事件写入同一事务。
  2. 独立进程轮询事件表,发布到MQ。

代码示例

java 复制代码
// 发布事件
@Transactional
public void createOrder(Order order) {
    orderRepository.save(order);
    outboxRepository.save(new OutboxEvent("order_created", order.getId()));
}

优劣势

优势 :解耦业务与消息发送,适合微服务架构。

劣势:增加轮询开销,可能引入延迟。


四、事务生命周期与监控

1. 事务状态记录

唯一事务ID :全局唯一标识符(如UUID)。

状态跟踪:记录事务的开始、提交、回滚状态。

数据库表设计

sql 复制代码
CREATE TABLE transaction_logs (
    tx_id VARCHAR(36) PRIMARY KEY,
    service_name VARCHAR(50),
    status ENUM('STARTED', 'COMMITTED', 'ROLLBACKED'),
    created_time TIMESTAMP,
    updated_time TIMESTAMP
);

2. 监控与告警

核心指标

事务成功率 :统计各服务事务成功/失败比例。

延迟分布:P50、P90、P99事务处理时间。

告警规则

yaml 复制代码
# Prometheus告警配置
groups:
- name: transaction-alerts
  rules:
  - alert: HighTransactionFailureRate
    expr: sum(rate(transaction_failed_total[5m])) / sum(rate(transaction_total[5m])) > 0.05
    labels:
      severity: critical
    annotations:
      summary: "事务失败率超过5% (当前值: {{ $value }})"

人工介入流程

  1. 异常标记:监控系统标记状态为"待处理"的事务。
  2. 人工处理:通过管理后台查看详情,触发补偿或通知开发。

五、方案对比与选型建议

方案 一致性 性能 复杂度 适用场景
Seata AT 传统业务迁移
XA两阶段提交 金融转账
TCC 高并发秒杀
Saga 最终 长流程事务(电商订单)
事务消息 最终 异步通知场景
Transactional Outbox 最终 微服务解耦
相关推荐
心灵宝贝38 分钟前
IDEA 安装 SpotBugs 插件超简单教程
java·macos·intellij-idea
幼稚诠释青春42 分钟前
Java学习笔记(对象)
java·开发语言
小羊学伽瓦1 小时前
【Java基础】——JVM
java·jvm
老任与码1 小时前
Spring AI(2)—— 发送消息的API
java·人工智能·spring ai
*.✧屠苏隐遥(ノ◕ヮ◕)ノ*.✧1 小时前
MyBatis快速入门——实操
java·spring boot·spring·intellij-idea·mybatis·intellij idea
csdn_freak_dd2 小时前
查看单元测试覆盖率
java·单元测试
爱吃烤鸡翅的酸菜鱼2 小时前
【SpringMVC】详解cookie,session及实战
java·http·java-ee·intellij-idea
Wyc724092 小时前
JDBC:java与数据库连接,Maven,MyBatis
java·开发语言·数据库
Lucas6492 小时前
kafka的安装及简单使用
分布式·kafka
掘金-我是哪吒2 小时前
分布式微服务系统架构第127集:cassandra安装部署
分布式·微服务·云原生·架构·系统架构