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

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

一、核心目标

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

  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 最终 中 高 微服务解耦
相关推荐
别动我齐刘海8 小时前
C++ 工程化学习
java·linux·前端·c++·学习·机器学习·机器人
loulanyue_8 小时前
从个人提效到团队可验证交付:中宏保险AI Coding流水线重塑与Qoder实战——读中宏保险AI架构总监王志宇2026云栖专场演讲
人工智能·架构
code2cat9 小时前
Java进阶篇之AtomicLongFieldUpdater:把累计额度留在对象字段中
java·cas·并发编程
WeiXin_DZbishe9 小时前
基于springboot城市公交实时运营与调度系统-计算机毕设 附源码【课程设计】66173
java·vue.js·spring boot·后端·python·php·课程设计
泡茶喝茶写代码9 小时前
A股量化数据工程:从 REST 接口到策略信号(第 18 篇):放量缩量异动扫描
java·python·股票数据api·股票数据api接口·股票api数据接口·股票量化数据api·股票量化数据接口
wewowilling10 小时前
认识微服务
java·运维·微服务·springcloud
Erishen10 小时前
Lume C11编译器内部架构:从树形解释器到双LLVM后端的设计之旅
架构·开源·编译器
代码什么用10 小时前
Java Web 7-10
java·servlet
沪上企服通10 小时前
历史账套科目重映射与规则版本重算:旧账梳理的“口径复位”工程
笔记·架构