簡介
「每服務資料庫」是微服務的基礎模式。沒有它,您就沒有真正的微服務——只有共享相同資料庫的模組(分散式整體)。本文解釋了原因、如何選擇正確的資料庫以及如何處理資料共享。

1. 為什麼每個服務都有資料庫?
1.1 共享資料庫-分散式單體之路
❌ Shared Database Anti-pattern:
┌────────┐ ┌────────┐ ┌────────┐
│User µS │ │Order µS│ │Payment │
└───┬────┘ └───┬────┘ └───┬────┘
│ │ │
└──────────┼──────────┘
▼
┌─────────────────────┐
│ Shared PostgreSQL │
│ ├── users │ ← ai own schema này?
│ ├── orders │ ← coupling tại data layer
│ ├── payments │ ← thay đổi schema = break all
│ └── products │
└─────────────────────┘
問題:
- 架構變更影響所有服務
- 無法獨立擴充資料庫
- 緊耦合-部署必須同時進行
- 不能針對不同的用例使用不同的資料庫
1.2 每個服務的資料庫
✅ Database per Service:
┌────────┐ ┌────────┐ ┌────────┐
│User µS │ │Order µS│ │Cart µS │
└───┬────┘ └───┬────┘ └───┬────┘
│ │ │
▼ ▼ ▼
┌────────┐ ┌────────┐ ┌────────┐
│PostgreSQL│ │PostgreSQL│ │ Redis │
│(users) │ │(orders) │ │(carts) │
└─────────┘ └─────────┘ └────────┘
Mỗi service own data riêng.
Schema changes chỉ ảnh hưởng 1 service.
Có thể chọn DB phù hợp nhất cho use case.
2. 多語言持久性 — 選擇正確的資料庫
2.1 決策矩陣
| 使用案例 | 資料庫 | 為什麼 |
|---|---|---|
| 使用者資料、訂單 | PostgreSQL | ACID、關係型、成熟 |
| 產品目錄 | PostgreSQL + Elasticsearch | 關係+全文搜尋 |
| 購物車 | Redis | 快速、短暫、TTL 支援 |
| 會話儲存 | Redis | 記憶體中,快速過期 |
| 活動日誌、事件 | MongoDB / 卡夫卡 | 模式靈活,僅附加 |
| 推薦 | Neo4j / Redis | 圖形關係/快取 |
| 分析/商業智慧 | ClickHouse / BigQuery | 柱狀、快速聚合 |
2.2 電商平台資料庫設計
┌─────────────────────────────────────────────┐
│ User Service → PostgreSQL │
│ users, addresses, preferences │
├─────────────────────────────────────────────┤
│ Product Service → PostgreSQL + Elasticsearch│
│ products, categories, reviews (PG) │
│ search index (ES) │
├─────────────────────────────────────────────┤
│ Cart Service → Redis │
│ cart:{userId} → JSON (items, quantities) │
│ TTL: 7 days (auto-expire abandoned carts) │
├─────────────────────────────────────────────┤
│ Order Service → PostgreSQL │
│ orders, order_items, order_status_history │
├─────────────────────────────────────────────┤
│ Payment Service → PostgreSQL │
│ transactions, refunds, payment_methods │
└─────────────────────────────────────────────┘
3. 資料共享模式
當服務A需要來自服務B的資料時:
3.1 API組成
服務A需要資料時呼叫服務B的API。簡單但會產生運行時依賴性。
3.2 事件承載狀態轉移
服務 B 發布包含資料的事件 → 服務 A 儲存本機副本。
ProductService publishes: ProductUpdated {id, name, price, image}
OrderService subscribes → lưu product snapshot trong order_items
→ Không cần gọi ProductService khi hiển thị order history
3.3 CQRS(詳見第9課)
從事件建立讀取最佳化的檢視 - 專用查詢服務。
4.架構遷移策略
每個服務管理自己的架構:
- Flyway / Liquibase (Java) 或 Prisma Migrate / Knex (Node.js)
- 原始碼中的遷移腳本版本
- 向後相容的變更:新增列(可為空白)、新增資料表
- 重大變更:多階段遷移(新增新的→遷移資料→刪除舊的)
總結
- 每個服務的資料庫對於真正的微服務來說是不可協商的
- 根據用例選擇資料庫(多語言持久性)
- 透過事件(首選)或API呼叫進行資料共享
- 架構遷移是每個服務團隊的責任
下一篇文章: 第 8 課:Saga 模式與分散式事務