以下是当前主流的分布式事务解决方案,结合技术演进和实际应用场景分类说明:
1. 两阶段提交 (2PC)
- 原理 :通过协调器分
准备阶段
和提交阶段
控制多个参与者的事务状态 - 特点:强一致性、数据库原生支持(XA协议)、同步阻塞
- 适用场景:传统单体应用、数据库层跨库事务(如银行转账)
银行跨行转账流程: 用户 → A行柜面系统 → A行核心账务系统 → 支付清算系统 → B行核心账务系统 → B行柜面系统 (2PC协调者) (2PC参与者)
2PC 的核心风险与应对策略
一、主要风险分析
风险点 | 具体表现 | 影响场景 |
---|---|---|
协调者单点故障 | 协调者宕机导致事务状态丢失,参与者阻塞 | 所有阶段 |
同步阻塞 | 所有参与者在Prepare 后等待协调者指令,期间资源被锁定 |
高并发场景下性能骤降 |
数据不一致 | 部分参与者提交成功,其他参与者因网络/宕机未收到指令 | Commit阶段协调者宕机 |
资源锁长期持有 | 事务处理时间长时,锁未释放引发死锁或并发瓶颈 | 大事务或慢查询 |
网络分区(脑裂) | 协调者与参与者网络中断,误判节点状态 | 跨机房部署 |
二、针对性应对策略
1. 协调者单点故障
-
解决方案:
- 集群化部署 :使用
Raft/Paxos
协议实现协调者主备切换(如ETCD/ZooKeeper) - 事务日志持久化:将事务状态实时写入共享存储(如HDFS/Redis Cluster)
java// 伪代码:协调者持久化事务日志 public void saveTransactionLog(Transaction tx) { distributedStorage.write(tx.getId(), tx.serialize()); }
- 集群化部署 :使用
-
效果:故障恢复后可从日志重建事务状态,RTO(恢复时间目标)<1分钟
2. 同步阻塞
-
解决方案:
- 超时中断:设置阶段等待超时阈值(如Prepare阶段10秒),超时自动回滚
- 异步化改造:将阻塞等待转为事件驱动(如参与者回调通知)
plaintext[优化流程] 协调者发送Prepare → 立即释放线程 → 异步监听参与者响应 → 超时/响应后触发后续动作
-
效果:系统吞吐量提升3-5倍(实测数据)
3. 数据不一致
-
解决方案 :
-
最终一致性兜底:
- 事务状态表:记录全局事务ID及参与者状态
- 定时对账任务:扫描悬挂事务(如超过24小时未完结)
- 人工/自动修复:基于日志补偿不一致数据
sql-- 示例:对账系统SQL SELECT * FROM transaction WHERE status = 'committed' AND EXISTS (SELECT 1 FROM participant WHERE participant.tx_id = transaction.id AND status != 'committed');
-
业务幂等设计:参与者接口支持重试(如唯一事务ID去重)
-
-
效果:资损率降至0.001%以下(银行级要求)
4. 资源锁长期持有
-
解决方案:
- 锁粒度优化:从表锁降级为行锁,结合索引减少锁定范围
- 锁超时释放:设置锁自动释放时间(如30秒),超时后事务回滚
sql-- MySQL行锁示例(FOR UPDATE SKIP LOCKED) SELECT * FROM account WHERE id = 'A' FOR UPDATE SKIP LOCKED;
-
效果:死锁率减少90%,并发能力提升
5. 网络分区
-
解决方案 :
- 探活机制:双向心跳检测(协调者↔参与者)
- 保守决策:网络恢复前冻结资金操作,防止资损
plaintext[网络中断处理] 1. 参与者:若未收到协调者心跳,将本地事务标记为"可疑" 2. 协调者:检测到节点失联,暂停新事务路由至该节点 3. 恢复后:优先同步事务状态,再开放新请求
2. TCC 模式 (Try-Confirm-Cancel)
- 原理 :业务层通过
Try(资源预留) → Confirm/Cancel(提交/回滚)
三个阶段实现补偿 - 特点:业务侵入性强、需自定义回滚逻辑、最终一致性
- 适用场景:高并发场景(如电商库存扣减)、需细粒度控制的业务
Seata TCC 模式的实现原理基于 两阶段提交(2PC) ,通过 业务层的补偿机制 实现分布式事务的最终一致性。以下是实现机制:
一、核心角色与组件
角色 | 职责 |
---|---|
TM (Transaction Manager) | 定义全局事务边界(@GlobalTransactional ),发起事务的提交或回滚 |
TC (Transaction Coordinator) | 事务协调器(独立服务),维护全局事务状态,驱动分支事务的提交或回滚 |
RM (Resource Manager) | 管理分支事务资源(如TCC接口),向TC注册分支事务状态,执行Confirm/Cancel逻辑 |
二、TCC 接口定义规则
Seata 通过 注解驱动 定义TCC接口,需满足以下条件:
- 接口必须声明为
@LocalTCC
:标识该接口为TCC模式 - Try方法标注
@TwoPhaseBusinessAction
:指定commit和rollback方法名 - Confirm/Cancel方法需匹配声明 :参数类型为
BusinessActionContext
示例代码:
java
@LocalTCC
public interface InventoryTccService {
// Try阶段:资源预留
@TwoPhaseBusinessAction(
name = "prepareDeduct",
commitMethod = "commitDeduct",
rollbackMethod = "cancelDeduct")
boolean prepareDeduct(
@BusinessActionContextParameter(paramName = "productId") String productId,
@BusinessActionContextParameter(paramName = "count") int count);
// Confirm阶段:提交
boolean commitDeduct(BusinessActionContext context);
// Cancel阶段:回滚
boolean cancelDeduct(BusinessActionContext context);
}
三、事务执行流程
阶段1:Try(资源预留)
-
TM 发起全局事务:
java@GlobalTransactional public void createOrder() { inventoryTccService.prepareDeduct("P1001", 2); // 调用Try couponTccService.prepareLockCoupon("C2001"); }
-
RM 注册分支事务:
- 每个Try方法执行时,RM向TC注册分支事务,TC记录事务日志到
global_table
和branch_table
- 每个Try方法执行时,RM向TC注册分支事务,TC记录事务日志到
-
资源锁定:
- 执行Try逻辑(如库存预扣减),资源状态标记为
预占用
- 执行Try逻辑(如库存预扣减),资源状态标记为
阶段2:Confirm/Cancel(提交/回滚)
-
成功场景(Confirm):
- TM通知TC提交事务 2 TC异步调用所有RM的Confirm方法 3 RM执行真实业务提交(如实际扣减库存)
-
失败场景(Cancel):
- TM通知TC回滚事务 2 TC调用所有RM的Cancel方法 3 RM执行补偿逻辑(如释放预扣库存)
四、异常处理机制
1. 幂等性控制
-
问题:网络重试导致Confirm/Cancel重复调用
-
解决 :TC维护事务状态,RM通过
branch_table
状态判断是否已处理sql-- branch_table结构 CREATE TABLE branch_table ( branch_id BIGINT PRIMARY KEY, xid VARCHAR(128) NOT NULL, -- 全局事务ID status TINYINT NOT NULL, -- 状态:1-Try, 2-Confirm, 3-Cancel gmt_create DATETIME, gmt_modified DATETIME );
2. 空回滚(Cancel without Try)
-
场景:Try未执行但收到Cancel请求(如Try超时)
-
处理 :RM在Cancel方法中检查Try是否执行
javapublic boolean cancelDeduct(BusinessActionContext context) { String xid = context.getXid(); // 查询分支事务是否存在 if (!branchTableDao.existsBranch(xid, "inventory")) { // 记录空回滚日志 logEmptyRollback(xid); return true; } // 正常执行Cancel逻辑... }
3. 防悬挂(Confirm/Cancel早于Try)
-
场景:Try因网络延迟在Confirm/Cancel之后到达
-
处理 :TC拒绝处理超时的Try请求
javapublic boolean prepareDeduct(String productId, int count) { // TC检查全局事务是否已超时 if (globalTransaction.isTimeout()) { throw new ShouldNeverHappenException("Try请求已超时"); } // 正常执行Try... }
五、事务恢复机制
1. 事务状态扫描
-
TC 定时任务 :扫描
global_table
中状态为Begin
且超时的事务java@Scheduled(fixedDelay = 5000) public void checkTimeoutTransactions() { List<GlobalTransaction> timeoutTxns = globalTableDao.selectTimeout(60); // 超时60秒 timeoutTxns.forEach(txn -> txn.setStatus(GlobalStatus.TimeoutRollbacking)); }
2. 重试策略
- 最大重试次数 :默认3次,可通过
client.undo.log.table
配置 - 回滚策略 :
- 若Try阶段有部分成功:触发所有已Try的Cancel
- 若所有Try均未成功:直接删除事务日志
六、上下文传播机制
1. XID 传递
- HTTP 请求 :通过Header传递
Seata-Xid
(如XID:192.168.1.1:8091:123456
) - RPC 框架 :通过隐式参数传递(如Dubbo的
RpcContext
)
2. 业务上下文存储
-
BusinessActionContext :自动保存Try阶段的参数,供Confirm/Cancel使用
javapublic boolean commitDeduct(BusinessActionContext context) { String productId = context.getActionContext("productId"); int count = (int) context.getActionContext("count"); // 执行业务提交... }
七、高可用与性能优化
1. TC 集群部署
- 注册中心集成:支持Nacos、Eureka等,实现TC节点发现
- 数据持久化:事务日志存储到数据库(MySQL)或Redis
2. 异步化处理
-
Confirm/Cancel 异步执行 :通过线程池提交任务,避免阻塞主线程
javapublic void asyncCommit(String xid) { executor.submit(() -> { for (BranchTransaction branch : getBranches(xid)) { branch.commit(); } }); }
总结
plaintext
Seata TCC = 注解定义接口 + 两阶段提交 + 事务状态追踪 + 异常三原则处理 + 集群高可用
适用场景:需细粒度控制事务(如库存冻结)、高并发业务(如秒杀)、跨异构系统(如非Java服务)
3. Saga 模式
- 原理:将长事务拆分为多个本地事务,通过正向操作+逆向补偿操作保证最终一致性
- 实现方式:编排式(中央协调器) / 协同式(事件驱动)
- 适用场景:跨服务的长流程业务(如订单→支付→物流)
一、核心设计思想
- 长事务拆分:将长时间运行的分布式事务拆分为多个本地事务
- 事件驱动:通过事件/命令触发后续事务执行
- 补偿机制 :为每个正向操作定义对应的补偿操作(
compensateOrder
)
二、两种实现模式对比
1. 协同式(Choreography)
特点:
- 服务间直接通信
- 无中央协调器
- 适合简单业务流程
2. 编排式(Orchestration)
特点:
- 中央协调器统一调度
- 流程可视化程度高
- 适合复杂业务流程
三、补偿事务设计原则
- 幂等性 :补偿操作可重复执行(
retryCompensate
) - 可逆性:正向操作与补偿操作形成闭环
- 及时性:需在业务允许的时间窗口内完成
- 原子性:每个本地事务独立完成
示例代码:
java
// 订单服务补偿操作
public void compensateOrder(Long orderId) {
// 1. 检查订单状态
OrderStatus status = orderRepository.getStatus(orderId);
// 2. 幂等性检查
if(status == OrderStatus.CANCELED) return;
// 3. 执行补偿逻辑
orderRepository.updateStatus(orderId, OrderStatus.CANCELED);
inventoryService.restock(orderId); // 调用库存恢复
}
协同式补偿机制的实现详解
一、核心补偿原理
- 事件驱动补偿:每个服务完成本地事务后发布事件,下游服务监听事件并执行补偿
- 逆向操作链:通过发布逆向事件触发补偿流程
- 最终一致性:通过事件传播保证最终数据一致
二、典型补偿流程(以电商取消订单为例)
三、关键实现要素
1. 事件契约设计
java
// 订单取消事件
public class OrderCanceledEvent {
private String orderId;
private String cancelReason;
// 必须包含补偿所需全部参数
private List<ItemDTO> originalItems;
}
// 库存恢复事件
public class InventoryRestockedEvent {
private String warehouseId;
private Map<String, Integer> skuQtyMap;
}
2. 补偿操作实现
java
// 库存服务补偿处理器
@Service
public class InventoryCompensator {
@Transactional
@EventListener(OrderCanceledEvent.class)
public void handleOrderCancel(OrderCanceledEvent event) {
// 1. 幂等检查
if(compensationLog.exists(event.getOrderId())) return;
// 2. 执行补偿逻辑
inventoryRepository.restock(
event.getOriginalItems()
);
// 3. 记录补偿日志
compensationLog.save(event.getOrderId());
// 4. 触发下一级补偿
eventBus.publish(new InventoryRestockedEvent(...));
}
}
3. 补偿触发机制
- 正向操作失败:本地事务回滚时自动发布补偿事件
- 超时补偿:定时任务扫描未完成事务
java
@Scheduled(fixedRate = 5000)
public void checkCompensationTimeout() {
List<Order> timeoutOrders = orderRepository.findByStatusAndTimeout(
OrderStatus.PENDING,
LocalDateTime.now().minusMinutes(30)
);
timeoutOrders.forEach(order -> {
eventBus.publish(new OrderCanceledEvent(order.getId()));
});
}
四、异常处理设计
1. 重试策略
java
@Retryable(
value = {OptimisticLockException.class},
maxAttempts = 3,
backoff = @Backoff(delay = 1000)
)
public void processCompensation(CompensationEvent event) {
// 补偿处理逻辑
}
2. 死信队列处理
java
@KafkaListener(
topics = "compensation_dlq",
groupId = "compensation-group"
)
public void handleDeadLetter(CompensationEvent event) {
alertService.notifyAdmin(event); // 人工干预
compensationRetryQueue.retryLater(event); // 延迟重试
}
3. 补偿追踪
sql
CREATE TABLE compensation_trace (
trace_id VARCHAR(36) PRIMARY KEY,
service_name VARCHAR(50),
event_type VARCHAR(100),
status ENUM('PENDING','SUCCESS','FAILED'),
retry_count INT DEFAULT 0,
created_time DATETIME,
last_updated DATETIME
);
五、数据一致性保障
1. 本地事务与事件发布的原子性
java
@Transactional
public void cancelOrder(String orderId) {
// 1. 更新订单状态
orderRepository.updateStatus(orderId, OrderStatus.CANCELED);
// 2. 发布事件(与事务同步)
TransactionSynchronizationManager.registerSynchronization(
new TransactionSynchronization() {
@Override
public void afterCommit() {
eventBus.publish(new OrderCanceledEvent(orderId));
}
}
);
}
2. 最终一致性检查
java
@Scheduled(cron = "0 0 3 * * ?") // 每天凌晨3点检查
public void consistencyCheck() {
List<Order> abnormalOrders = orderRepository.findInconsistentOrders();
abnormalOrders.forEach(order -> {
eventBus.publish(new OrderCanceledEvent(order.getId()));
});
}
六、最佳实践
-
事件版本控制 :在事件中包含
version
字段处理协议变更 -
补偿优先级:设置不同补偿队列的优先级(如支付补偿优先于库存补偿)
-
监控指标:
java// 补偿成功率监控 @Aspect public class CompensationMonitor { @Around("@annotation(CompensationHandler)") public Object monitor(ProceedingJoinPoint pjp) { long start = System.currentTimeMillis(); try { return pjp.proceed(); } catch (Exception e) { metrics.recordFailure(); throw e; } finally { metrics.recordDuration(System.currentTimeMillis() - start); } } }
-
测试策略:
- 使用
Testcontainers
模拟分布式环境 - 注入故障测试网络分区场景
java@Test public void testCompensationChain() { // 1. 创建订单 Order order = createOrder(); // 2. 模拟支付服务宕机 paymentService.setUnavailable(); // 3. 触发取消 orderService.cancelOrder(order.getId()); // 4. 验证最终状态 await().atMost(30, SECONDS) .until(() -> inventoryService.getStock(itemId) == originalStock); }
- 使用
七、常见问题解决方案
问题现象 | 解决方案 |
---|---|
补偿事件丢失 | 使用支持持久化的消息队列(如Kafka) |
重复补偿 | 为每个补偿操作设计幂等逻辑 |
补偿死锁 | 设置补偿超时时间,超过阈值进入人工处理流程 |
服务不可用导致补偿失败 | 采用指数退避重试策略,配合断路器模式(如Resilience4j) |
跨服务数据追溯困难 | 在事件中携带全局事务ID(如X-B3-TraceId) |
编排式补偿机制的实现详解:
一、核心架构设计
二、补偿流程实现步骤
1. 定义状态机(以订单流程为例)
java
public class OrderSagaStateMachine {
// 正向操作定义
Step<OrderContext> createOrderStep = StepBuilder
.<OrderContext>builder()
.name("createOrder")
.compensation("cancelOrder")
.action(ctx -> orderService.create(ctx.getOrder()))
.build();
// 补偿操作定义
Step<OrderContext> cancelOrderStep = StepBuilder
.<OrderContext>builder()
.name("cancelOrder")
.action(ctx -> orderService.cancel(ctx.getOrderId()))
.build();
}
2. 协调器实现原理
java
public class SagaOrchestrator {
// 持久化存储执行日志
@Transactional
public void execute(SagaInstance saga) {
for (SagaStep step : saga.getSteps()) {
try {
// 执行正向操作
step.getAction().execute();
saga.logStepSuccess(step);
} catch (Exception e) {
// 触发补偿流程
compensate(saga, step);
break;
}
}
}
private void compensate(SagaInstance saga, SagaStep failedStep) {
List<SagaStep> reversedSteps = reverse(saga.getCompletedSteps());
for (SagaStep step : reversedSteps) {
step.getCompensation().execute();
saga.logCompensation(step);
}
}
}
三、关键组件设计
1. 补偿策略配置
yaml
# 补偿策略配置示例
saga:
policies:
order_flow:
maxRetries: 3
backoff: 1000ms
compensationOrder: LIFO # 后进先出补偿顺序
timeout: 30s
2. 状态持久化设计
java
@Entity
public class SagaInstance {
@Id
private String sagaId;
private SagaStatus status;
@OneToMany(cascade = CascadeType.ALL)
private List<SagaStepRecord> stepRecords;
@Version
private Long version; // 乐观锁控制
}
@Entity
public class SagaStepRecord {
private String stepName;
private StepStatus status;
private LocalDateTime executeTime;
private int retryCount;
}
3. 补偿触发机制
java
// 协调器的补偿处理逻辑
public void handleCompensation(String sagaId) {
SagaInstance saga = repository.findById(sagaId);
if (saga.getStatus() == SagaStatus.FAILED) {
List<SagaStep> stepsToCompensate = saga.getCompletedSteps()
.stream()
.sorted(Comparator.reverseOrder())
.collect(Collectors.toList());
stepsToCompensate.forEach(step -> {
try {
step.getCompensation().execute();
saga.markStepCompensated(step);
} catch (Exception e) {
handleCompensationFailure(saga, step, e);
}
});
}
}
四、异常处理设计
1. 重试机制实现
java
@Retryable(
maxAttempts = 3,
backoff = @Backoff(delay = 1000, multiplier = 2),
retryFor = {ServiceUnavailableException.class}
)
public void executeCompensation(CompensationTask task) {
// 实际补偿操作
}
2. 死信队列处理
java
@KafkaListener(topics = "saga_compensation_dlq")
public void processDeadLetter(CompensationMessage message) {
log.error("补偿最终失败: {}", message);
alertService.notifyAdmin(message);
repository.markAsTerminalFailure(message.getSagaId());
}
3. 最终保障措施
java
@Scheduled(fixedDelay = 60000)
public void recoverHungSagas() {
List<SagaInstance> hungSagas = repository.findHungSagas();
hungSagas.forEach(saga -> {
if (saga.getStatus() == SagaStatus.COMPENSATING) {
compensationExecutor.resume(saga);
}
});
}
五、数据一致性保障
1. 幂等性设计
java
public class OrderService {
@Compensation(name = "cancelOrder")
public void cancelOrder(String orderId) {
// 通过版本号控制幂等
Order order = orderRepository.findById(orderId);
if (order.getVersion() > cancellationRecord.getVersion()) {
throw new StaleStateException();
}
order.cancel();
orderRepository.save(order);
}
}
2. 补偿日志追踪
sql
-- 补偿追踪表设计
CREATE TABLE saga_compensation_log (
log_id BIGINT PRIMARY KEY,
saga_id VARCHAR(36),
step_name VARCHAR(50),
status ENUM('PENDING','SUCCESS','FAILED'),
retry_count INT DEFAULT 0,
created_time DATETIME,
last_updated DATETIME,
INDEX idx_saga_status (saga_id, status)
);
六、最佳实践建议
1. 协调器高可用设计
2. 补偿操作设计原则
- 原子性:每个补偿操作必须是独立的本地事务
- 可追溯:保留原始操作的所有上下文数据
- 兼容性:处理业务逻辑变更的版本兼容问题
- 隔离性:补偿操作不应影响正常业务流程
3. 推荐工具框架
七、典型补偿场景处理
场景 | 处理策略 |
---|---|
部分补偿失败 | 记录失败点,人工干预后继续执行剩余补偿 |
网络分区 | 采用Quorum机制确认协调器状态 |
业务逻辑版本冲突 | 在补偿操作中携带业务版本号 |
资源不足导致补偿失败 | 动态降低补偿优先级,优先处理关键业务补偿 |
补偿操作性能瓶颈 | 采用分级补偿策略,优先回滚核心资源 |
四、典型应用场景
- 电商订单流程(创建订单→扣库存→支付→发货)
- 酒店预订系统(订房→支付→确认订单)
- 机票预订系统(订票→选座→支付)
- 物流调度系统(接单→派车→装货→运输)
五、Saga模式优缺点
优点:
- 🚀 避免长时间资源锁定
- 🔗 服务间松耦合
- ⏱️ 支持最终一致性
- 🛠️ 天然适合微服务架构
缺点:
- ⚠️ 存在数据不一致窗口期
- 🔄 补偿逻辑实现复杂度高
- 📉 调试追踪困难
- ⏳ 可能产生脏读
六、最佳实践建议
-
事务拆分原则:
- 单个本地事务处理单一业务功能
- 事务粒度控制在秒级完成
-
补偿设计技巧:
- 优先采用逆向业务操作而非物理删除
- 补偿操作需携带原始请求参数(
originalRequest
)
-
监控关键指标:
java// 监控埋点示例 @Around("@annotation(sagaStep)") public Object monitor(ProceedingJoinPoint pjp) { long start = System.currentTimeMillis(); try { return pjp.proceed(); } finally { metrics.recordDuration(System.currentTimeMillis() - start); } }
-
推荐框架:
七、与TCC模式对比
特性 | Saga | TCC |
---|---|---|
一致性 | 最终一致性 | 强一致性 |
实现复杂度 | 中(需设计补偿) | 高(需实现Try/Confirm/Cancel) |
事务时长 | 适合分钟级长事务 | 适合秒级短事务 |
资源锁定 | 无锁定 | 资源预留 |
适用场景 | 跨多服务的业务流程 | 资金类高一致性操作 |
4. 基于消息队列
- 本地消息表:业务与消息表在同一个事务中写入,异步重试投递
- 事务消息 :RocketMQ 的
Half Message
机制(两阶段消息) - 特点:异步解耦、需处理消息重复消费
- 适用场景:数据最终一致性要求较高的场景(如支付成功通知)
5. 最大努力通知
- 原理:服务方尽最大努力发送通知,接收方主动查询兜底
- 特点:业务逻辑简单、需对账机制
- 适用场景:对一致性要求不高的场景(如短信通知)
6. Seata 框架
- AT 模式:自动生成反向SQL,基于全局锁实现事务隔离(类似2PC优化版)
- XA 模式:标准XA协议实现
- 特点:对业务代码低侵入、支持多语言
- 适用场景:微服务架构下的分布式事务统一管理
Seata框架的核心实现原理详解:
一、整体架构设计
核心组件:
- TC (Transaction Coordinator):事务协调器(独立部署)
- TM (Transaction Manager):事务管理器(集成在客户端)
- RM (Resource Manager):资源管理器(集成在数据源代理)
二、AT模式(Auto Transaction)实现原理
1. 第一阶段:业务SQL执行
java
// 数据源代理伪代码
public class DataSourceProxy {
public Connection getConnection() {
return new ConnectionProxy(realConnection);
}
}
class ConnectionProxy {
public void execute(String sql) {
// 1. 解析SQL获取前后镜像
TableMeta meta = getTableMeta(sql);
BeforeImage beforeImage = selectForUpdate(meta);
// 2. 执行原始SQL
realConnection.execute(sql);
// 3. 生成undo log
AfterImage afterImage = select(meta);
UndoLog undoLog = buildUndoLog(beforeImage, afterImage);
insertUndoLog(undoLog);
// 4. 注册分支事务到TC
registerBranchTransaction();
}
}
2. 第二阶段:全局提交/回滚
-
提交:异步删除undo log
-
回滚 :
sql/* 回滚示例 */ UPDATE account SET balance = 100 WHERE id = 1; -- 根据undo log恢复 DELETE FROM undo_log WHERE xid = '全局事务ID';
3. 全局锁机制
三、TCC模式实现原理
1. 三阶段流程
java
// TCC接口定义示例
public interface OrderTccService {
@TwoPhaseBusinessAction(name = "createOrder", commitMethod = "commit", rollbackMethod = "rollback")
boolean prepare(BusinessActionContext context, Order order);
boolean commit(BusinessActionContext context);
boolean rollback(BusinessActionContext context);
}
2. 事务控制表
sql
CREATE TABLE tcc_fence_log (
xid VARCHAR(128) NOT NULL,
action_name VARCHAR(64) NOT NULL,
status TINYINT NOT NULL,
gmt_create DATETIME,
PRIMARY KEY (xid, action_name)
);
四、XA模式实现原理
1. 标准XA协议实现
五、核心设计要点
1. 事务上下文传播
java
// 事务上下文传递
public class SeataInterceptor {
public void handleRequest(HttpServletRequest req) {
String xid = req.getHeader("TX_XID");
RootContext.bind(xid); // 绑定到线程上下文
}
}
2. 高可用设计
3. 异常恢复机制
java
// 事务恢复定时任务
@Scheduled(fixedRate = 5000)
public void recover() {
List<GlobalSession> sessions =
coordinator.findSessions(GlobalStatus.TimeoutRollbacking);
sessions.forEach(session -> {
coordinator.doGlobalRollback(session);
});
}
六、性能优化策略
-
异步化处理:二阶段提交异步执行
-
批量日志写入:合并undo log的数据库操作
-
全局锁优化:
properties# 锁竞争优化配置 store.db.lockRetryInterval=10ms store.db.lockRetryTimes=30
-
TC集群分区:按业务分片处理不同事务
七、与同类框架对比
特性 | Seata | Atomikos | Narayana |
---|---|---|---|
事务模式 | AT/TCC/Saga/XA | XA | XA/JTA |
侵入性 | 低(AT模式无侵入) | 高 | 高 |
性能 | 高(AT模式优化) | 中等 | 中等 |
部署复杂度 | 需部署TC | 无需额外组件 | 需JTA环境 |
社区生态 | 活跃(阿里背书) | 稳定 | 红帽支持 |
八、典型应用场景
- 电商订单系统:使用AT模式处理订单-库存-支付事务
- 金融转账系统:采用TCC模式保证资金操作强一致性
- 物流调度系统:通过Saga模式处理长流程事务
- 传统ERP系统:使用XA模式兼容老系统
最佳实践建议:
- AT模式适合80%的常规场景,优先考虑使用
- 高并发资金操作使用TCC模式
- TC集群部署至少3节点保证高可用
- 配合
Nacos
配置中心实现动态参数调整 - 使用
Seata-spring-boot-starter
简化集成
xml
<!-- Maven依赖示例 -->
<dependency>
<groupId>io.seata</groupId>
<artifactId>seata-spring-boot-starter</artifactId>
<version>1.7.0</version>
</dependency>
选型建议
维度 | 推荐方案 |
---|---|
强一致性要求 | 2PC/Seata XA |
高并发低延迟 | TCC/Saga |
异步解耦场景 | 消息队列方案 |
简单业务场景 | 最大努力通知 |
最新趋势 (2024年资料显示):混合方案使用增加,例如Saga+消息队列
组合解决复杂事务流,同时开源框架(如Seata)的AT模式因低侵入性被广泛采用。