在上一篇我們談過 Shared Database 與 Database per Service 的設計。結論是:在微服務架構中,Database per Service 雖然帶來了自治性與彈性,但也同時打破了傳統「跨表 Join」的便利。
換句話說,原本只要一條 SQL 就能完成的查詢,現在可能需要跨越多個微服務、甚至多種資料庫,這對開發與系統設計帶來了新的挑戰。(我今年好像一直在這個循環裡面繞 …)
今天,我們就來探討兩個常見的解決模式:
假設我們有一個線上商店系統,它包含下列微服務:
當前端要顯示「客戶詳細資訊」時,通常需要以下資料:
在傳統單體式應用中,我們只要寫一個 SQL Join:
SELECT c.customer_id, c.name, o.order_id, p.product_name, p.price
FROM customer c
JOIN orders o ON c.customer_id = o.customer_id
JOIN products p ON o.product_id = p.product_id
WHERE c.customer_id = 123;
但在微服務架構中,資料分散在三個不同服務、三個不同資料庫,這樣的 SQL 查詢不再可能。
API Composition 是一種 透過 API 組合不同微服務的查詢結果 的設計模式。
它的角色分成兩類:
以「客戶詳細資訊查詢」為例:
結果可能是這樣:
{
"customer": {
"id": 123,
"name": "Alice",
"creditLimit": 5000
},
"orders": [
{
"orderId": 1001,
"total": 200,
"items": [
{ "productName": "iPhone 15", "price": 150 },
{ "productName": "Phone Case", "price": 50 }
]
}
]
}
API Composition 的優點
API Composition 的限制與缺點
整理上述的內容,可以歸納在「查詢資料筆數少」、「即時性比一致性更重要」的情境可採用此模式。
CQRS(Command Query Responsibility Segregation,指令與查詢責任分離)是一種 將「寫」與「讀」分離 的設計模式。
一樣以「客戶詳細資訊查詢」為例:
優點:
缺點
整理上述的內容,可以歸納在「報表系統」、「BI 分析」、「批次程式」採用這個模式。
維度 | API Composition | CQRS |
---|---|---|
查詢方式 | 由 API Gateway/BFF 發送多次請求,組合結果 | 由查詢庫(Read DB)一次查詢 |
即時性 | 最新資料 | 可能有延遲(最終一致性) |
效能 | 跨多服務呼叫,延遲較高 | 高效能,查詢一次即可 |
適用場景 | 小量資料、即時性高 | 報表、大量查詢、跨服務數據整合 |
複雜度 | 簡單 | 複雜(需事件驅動架構) |
一致性 | 無交易一致性保證 | 最終一致性 |
在微服務架構下,跨資料庫查詢 是一個必然的挑戰。
一個成熟的微服務架構,往往 兩者並用:
最終,選擇的關鍵在於 需求優先順序:是要即時,還是要高效能?