引言

分布式事务是微服务架构的难点。本文介绍主流的分布式事务解决方案。

一、2PC(两阶段提交)

1
2
3
4
5
6
7
8
9
协调者                参与者
| |
|---准备(Prepare)--->|
| |
|<---同意/拒绝--------|
| |
|---提交(Commit)----->|
| |
|<---完成-------------|

优点:强一致性
缺点:性能差、阻塞

二、TCC(Try-Confirm-Cancel)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
public interface TccService {
// Try: 预留资源
@TccTransaction
boolean try(String orderId, BigDecimal amount);

// Confirm: 确认提交
boolean confirm(String orderId);

// Cancel: 取消释放
boolean cancel(String orderId);
}

@Service
public class AccountService implements TccService {
@Override
public boolean try(String orderId, BigDecimal amount) {
// 冻结余额
accountDao.freeze(orderId, amount);
return true;
}

@Override
public boolean confirm(String orderId) {
// 扣减余额
accountDao.deduct(orderId);
return true;
}

@Override
public boolean cancel(String orderId) {
// 解冻余额
accountDao.unfreeze(orderId);
return true;
}
}

三、Saga模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 正向服务
@Service
public class OrderSaga {
public void createOrder() {
// 1. 创建订单
orderService.create();
// 2. 扣减库存
inventoryService.deduct();
// 3. 扣减余额
accountService.deduct();
}
}

// 补偿服务
public void compensate() {
// 3. 恢复余额
accountService.add();
// 2. 恢复库存
inventoryService.add();
// 1. 取消订单
orderService.cancel();
}

四、消息最终一致性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
@Service
public class OrderService {
@Autowired
private KafkaTemplate<String, String> kafka;

@Transactional
public void createOrder(Order order) {
// 1. 创建订单
orderDao.insert(order);

// 2. 发送消息
kafka.send("order-topic", JSON.toJSONString(order));
}
}

@Service
public class InventoryService {
@KafkaListener(topics = "order-topic")
public void handleOrder(String message) {
Order order = JSON.parseObject(message, Order.class);
// 扣减库存
inventoryDao.deduct(order.getProductId(), order.getQuantity());
}
}

五、Seata框架

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@GlobalTransactional
public void purchase(String userId, String productId, int count) {
// 1. 创建订单
orderService.create(userId, productId, count);

// 2. 扣减库存
storageService.deduct(productId, count);

// 3. 扣减余额
accountService.deduct(userId, money);
}

// application.yml
seata:
registry:
type: nacos
config:
type: nacos
tx-service-group: my_tx_group

总结

分布式事务方案对比:

方案 一致性 性能 复杂度 适用场景
2PC 强一致 低 低 短事务
TCC 最终一致 高 高 对一致性要求高
Saga 最终一致 高 中 长事务
消息 最终一致 高 中 异步场景

参考资料