18.9.7 分布式事务解决方案(2PC/TCC/Saga)
1. 分布式事务基础概念
1.1 分布式事务问题
public class DistributedTransactionPrinciple {
/*
* 分布式事务核心问题:
*
* 1. ACID特性挑战
* - 原子性:多个服务要么全成功要么全失败
* - 一致性:数据状态保持一致
* - 隔离性:并发事务互不影响
* - 持久性:提交后数据持久保存
*
* 2. 常见场景
* - 订单支付:订单服务 + 支付服务 + 库存服务
* - 转账业务:账户A扣款 + 账户B加款
* - 电商下单:创建订单 + 扣减库存 + 扣减积分
*
* 3. 解决方案
* - 2PC (Two-Phase Commit)
* - TCC (Try-Confirm-Cancel)
* - Saga 模式
* - 本地消息表
* - 最大努力通知
*/
public void demonstrateDistributedTransaction() {
System.out.println("=== 分布式事务问题演示 ===");
demonstrateOrderPaymentScenario();
demonstrateTransferScenario();
}
private void demonstrateOrderPaymentScenario() {
System.out.println("--- 订单支付场景 ---");
OrderService orderService = new OrderService();
PaymentService paymentService = new PaymentService();
InventoryService inventoryService = new InventoryService();
System.out.println("1. 用户下单购买商品:");
String orderId = "order-001";
String userId = "user-123";
String productId = "product-456";
int quantity = 2;
double amount = 199.99;
System.out.println(" 订单ID: " + orderId);
System.out.println(" 商品: " + productId + " x " + quantity);
System.out.println(" 金额: " + amount);
System.out.println("\n2. 需要保证事务一致性:");
System.out.println(" - 创建订单成功");
System.out.println(" - 扣减库存成功");
System.out.println(" - 支付扣款成功");
System.out.println(" - 任一步骤失败则全部回滚");
System.out.println("\n3. 分布式事务挑战:");
System.out.println(" - 网络分区可能导致部分成功");
System.out.println(" - 服务故障可能导致状态不一致");
System.out.println(" - 需要协调多个服务的事务状态");
System.out.println();
}
private void demonstrateTransferScenario() {
System.out.println("--- 转账业务场景 ---");
System.out.println("1. 用户A向用户B转账:");
System.out.println(" 转出账户: account-A");
System.out.println(" 转入账户: account-B");
System.out.println(" 转账金额: 1000元");
System.out.println("\n2. 事务要求:");
System.out.println(" - 账户A扣款1000元");
System.out.println(" - 账户B加款1000元");
System.out.println(" - 保证资金总额不变");
System.out.println("\n3. 可能的问题:");
System.out.println(" - A扣款成功,B加款失败");
System.out.println(" - 网络故障导致状态未知");
System.out.println(" - 需要保证最终一致性");
System.out.println();
}
}
// 订单服务
class OrderService {
public boolean createOrder(String orderId, String userId, String productId, int quantity) {
System.out.println(" 订单服务: 创建订单 " + orderId);
// 模拟订单创建逻辑
return true;
}
public void cancelOrder(String orderId) {
System.out.println(" 订单服务: 取消订单 " + orderId);
}
}
// 支付服务
class PaymentService {
public boolean deductAmount(String userId, double amount) {
System.out.println(" 支付服务: 扣款 " + amount + " 元");
// 模拟支付扣款逻辑
return true;
}
public void refund(String userId, double amount) {
System.out.println(" 支付服务: 退款 " + amount + " 元");
}
}
// 库存服务
class InventoryService {
public boolean deductInventory(String productId, int quantity) {
System.out.println(" 库存服务: 扣减库存 " + quantity + " 个");
// 模拟库存扣减逻辑
return true;
}
public void restoreInventory(String productId, int quantity) {
System.out.println(" 库存服务: 恢复库存 " + quantity + " 个");
}
}
2. 2PC两阶段提交
2.1 2PC实现原理
public class TwoPhaseCommitDemo {
/*
* 2PC两阶段提交:
*
* 阶段一:准备阶段 (Prepare Phase)
* - 协调者向所有参与者发送准备请求
* - 参与者执行事务但不提交,返回准备结果
*
* 阶段二:提交阶段 (Commit Phase)
* - 如果所有参与者都准备成功,协调者发送提交请求
* - 如果任一参与者准备失败,协调者发送回滚请求
*
* 优点:强一致性保证
* 缺点:阻塞式协议,性能较差,存在单点故障
*/
public void demonstrate2PC() {
System.out.println("=== 2PC两阶段提交演示 ===");
TwoPhaseCommitCoordinator coordinator = new TwoPhaseCommitCoordinator();
// 添加参与者
coordinator.addParticipant(new OrderServiceParticipant("order-service"));
coordinator.addParticipant(new PaymentServiceParticipant("payment-service"));
coordinator.addParticipant(new InventoryServiceParticipant("inventory-service"));
demonstrate2PCSuccess(coordinator);
demonstrate2PCFailure(coordinator);
}
private void demonstrate2PCSuccess(TwoPhaseCommitCoordinator coordinator) {
System.out.println("--- 2PC成功场景 ---");
TransactionContext context = new TransactionContext("tx-001");
context.addOperation("createOrder", "order-001");
context.addOperation("deductPayment", "1000.0");
context.addOperation("deductInventory", "product-001:2");
boolean result = coordinator.executeTransaction(context);
System.out.println("事务执行结果: " + (result ? "成功" : "失败"));
System.out.println();
}
private void demonstrate2PCFailure(TwoPhaseCommitCoordinator coordinator) {
System.out.println("--- 2PC失败场景 ---");
TransactionContext context = new TransactionContext("tx-002");
context.addOperation("createOrder", "order-002");
context.addOperation("deductPayment", "insufficient"); // 模拟支付失败
context.addOperation("deductInventory", "product-002:1");
boolean result = coordinator.executeTransaction(context);
System.out.println("事务执行结果: " + (result ? "成功" : "失败"));
System.out.println();
}
}
// 事务上下文
class TransactionContext {
private String transactionId;
private java.util.Map<String, String> operations = new java.util.HashMap<>();
public TransactionContext(String transactionId) {
this.transactionId = transactionId;
}
public void addOperation(String operation, String data) {
operations.put(operation, data);
}
public String getTransactionId() { return transactionId; }
public java.util.Map<String, String> getOperations() { return operations; }
}
// 2PC协调者
class TwoPhaseCommitCoordinator {
private java.util.List<TransactionParticipant> participants = new java.util.ArrayList<>();
public void addParticipant(TransactionParticipant participant) {
participants.add(participant);
}
public boolean executeTransaction(TransactionContext context) {
System.out.println("开始执行2PC事务: " + context.getTransactionId());
// 阶段一:准备阶段
System.out.println("\n=== 阶段一:准备阶段 ===");
boolean allPrepared = true;
for (TransactionParticipant participant : participants) {
boolean prepared = participant.prepare(context);
System.out.println(participant.getName() + " 准备结果: " + (prepared ? "成功" : "失败"));
if (!prepared) {
allPrepared = false;
break;
}
}
// 阶段二:提交或回滚阶段
System.out.println("\n=== 阶段二:" + (allPrepared ? "提交" : "回滚") + "阶段 ===");
if (allPrepared) {
// 所有参与者准备成功,执行提交
for (TransactionP
剩余60%内容,订阅专栏后可继续查看/也可单篇购买
Java面试圣经 文章被收录于专栏
Java面试圣经,带你练透java圣经
