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

发布于:2025-03-27 ⋅ 阅读:(40) ⋅ 点赞:(0)

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

一、核心目标

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

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

二、强一致性方案

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

设计意图
简化开发:通过全局锁机制自动回滚事务,减少业务侵入。
适用场景:电商订单创建(扣库存+生成订单)。

技术实现
全局事务ID(XID):Seata客户端生成唯一ID,贯穿所有子事务。
数据快照:记录事务前后的数据镜像,用于自动回滚。

生产配置示例

# 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结果提交或回滚。

代码示例

// 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:回滚预留(如解冻库存)。

代码示例

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模式(正向+逆向补偿)

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

技术实现
正向操作:依次执行子事务(如创建订单 → 扣库存)。
补偿操作:逆向回滚(如取消订单 → 返还库存)。

代码示例

// 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. 异步校对(定时补偿)

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

技术实现
定时任务:扫描事务表,检查未完成的事务。
补偿触发:对异常事务执行修复(如重试或回滚)。

生产配置示例

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

优劣势
优势:实现简单,适合对一致性要求不高的场景(如日志记录)。
劣势:修复延迟,可能影响用户体验。


3. 事务消息(RocketMQ)

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

技术实现
半消息:消息暂存Broker,不可被消费。
事务状态回查:Broker定期检查生产者事务状态。

代码示例

// 发送事务消息
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。

数据库表设计

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。

代码示例

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

优劣势
优势:解耦业务与消息发送,适合微服务架构。
劣势:增加轮询开销,可能引入延迟。


四、事务生命周期与监控

1. 事务状态记录

唯一事务ID:全局唯一标识符(如UUID)。
状态跟踪:记录事务的开始、提交、回滚状态。

数据库表设计

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事务处理时间。

告警规则

# 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 最终 微服务解耦