簡介
在 Monolith 中,交易很簡單: BEGIN → INSERT order → UPDATE inventory → COMMIT。在微服務中,每個服務都有自己的DB→無法使用分散式ACID事務(2PC太慢、脆弱)。 傳奇模式是標準解決方案。

1. 問題:分散式事務
1.1 為什麼不適合2PC(兩階段提交)?
- 封鎖:所有參與者都被鎖定,直到協調員決定
- 單點故障:協調器崩潰→死鎖
- 效能受到影響:延遲顯著增加
- 無規模:新增參與者=增加複雜度指數
1.2 接受最終一致性
在微服務中,我們接受最終一致性而不是強一致性。數據將最終一致,而不是立即。
2.傳奇模式
Saga = 本地事務的字串,每個事務更新1個服務。如果交易失敗,補償事務將撤銷先前的變更。
2.1 基於編排的傳奇
每個服務發布事件→下一個服務監聽並執行:
Order Service Payment Service Inventory Service
│ │ │
│──OrderCreated───────►│ │
│ │──PaymentProcessed───►│
│ │ │──InventoryReserved──►
│ │ │
│ (nếu Inventory fail) │
│ │◄──InventoryFailed────│
│◄──PaymentRefunded────│ │
│──OrderCancelled │ │
**優點:**簡單、鬆散耦合、無中央協調器 缺點: 難以追蹤整體流程,可能存在循環依賴
2.2 基於編排的 Saga
Saga Orchestrator 協調整個流程:
┌─────────────────┐
│ Order Saga │
│ Orchestrator │
└──┬──┬──┬───────┘
│ │ │
┌──────────┘ │ └──────────┐
▼ ▼ ▼
┌──────────┐ ┌──────────┐ ┌──────────┐
│ Payment │ │Inventory │ │ Shipping │
│ Service │ │ Service │ │ Service │
└──────────┘ └──────────┘ └──────────┘
Orchestrator:
1. Create Order (PENDING)
2. Command: ProcessPayment → Payment Service
3. If success: Command: ReserveInventory → Inventory Service
4. If success: Command: CreateShipment → Shipping Service
5. If any fail: Compensate previous steps in reverse
**優點:**流程清晰,易於理解,集中錯誤處理 缺點: Orchestrator 可能成為瓶頸、單點故障
2.3 什麼時候使用什麼?
| 標準 | 編舞 | 編排 |
|---|---|---|
| 複雜性 | 2-3 步驟 | 4+ 步驟 |
| 可見性 | 難以追蹤 | 清除 |
| 聯軸器 | 寬鬆 | 媒介(到協調器) |
| 錯誤處理 | 分散式 | 集中式 |
3. 補償交易
補償事務=業務事務的「撤銷」(不是資料庫回滾):
Forward: Compensating:
CreateOrder → CancelOrder
ProcessPayment → RefundPayment
ReserveInventory → ReleaseInventory
CreateShipment → CancelShipment
注意:補償事務必須是冪等的-多次呼叫會得到相同的結果。
4. 冪等性-處理重複訊息
在分散式系統中,訊息可以發送多次(至少一次傳遞)。服務必須處理重複項:
// Idempotent payment processing
async function processPayment(command) {
// Check idempotency key
const existing = await db.findPayment(command.idempotencyKey);
if (existing) return existing; // Already processed
// Process payment
const result = await stripe.charge(command.amount);
await db.savePayment({
idempotencyKey: command.idempotencyKey,
...result
});
return result;
}
5. 實務:電子商務訂購傳奇
Create Order Saga (Orchestration):
Step 1: Order Service → CreateOrder(PENDING)
Step 2: Payment Service → ChargeCustomer(orderId, amount)
✅ → Step 3
❌ → Compensate: CancelOrder → DONE (Order: PAYMENT_FAILED)
Step 3: Inventory Service → ReserveItems(orderId, items)
✅ → Step 4
❌ → Compensate: RefundPayment → CancelOrder → DONE (Order: OUT_OF_STOCK)
Step 4: Order Service → ConfirmOrder(orderId)
✅ → DONE (Order: CONFIRMED)
Step 5 (async): Notification Service → SendConfirmationEmail
總結
- 2PC 不適合微服務 — 太慢且脆弱
- Saga Pattern = 本地事務序列 + 補償事務
- 編排:簡單流程(2-3步),鬆散耦合
- 編排:複雜的流程(4+步驟),清晰的可見性
- 冪等性是必要的-始終處理重複的訊息