Chuyển đến nội dung chính

第 7 課:每個服務的資料庫和多語言持久性

為什麼每個服務都需要自己的資料庫?選擇正確資料庫的策略:PostgreSQL、MongoDB、Redis、Elasticsearch。共享資料庫反模式。資料隔離、模式所有權和遷移策略。

🏗️ 建築 — 第 7 課 第 7 課:每個服務的資料庫和多語言 堅持

微服務與微前端系統設計-從基礎到生產

第 3 部分:微服務中的資料架構

亞洲開發網

簡介

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

每個服務都有資料庫-每個服務都有自己的資料庫


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 決策矩陣

使用案例資料庫為什麼
使用者資料、訂單PostgreSQLACID、關係型、成熟
產品目錄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 模式與分散式事務