為現代基礎設施設計資料模型需要根本性的思維轉變。傳統的實體關係圖(ERD)在單體架構中表現良好,其中單一資料庫實例負責管理所有交易。然而,隨著系統演進至分散式環境,資料完整性與關係映射的規則發生顯著變化。本指南探討專為複雜分散式交易系統量身打造的進階ERD模式。我們將研究如何建模一致性、跨服務管理狀態,並在不依賴特定軟體產品的情況下視覺化依賴關係。
在分散式環境中,資料所有權的界線變得模糊。實體可能存在于多個邏輯儲存位置,因此需要明確定義關係如何維持。本文檔提供了一種結構化的方法來建模這些複雜性。

🧠 分散式架構對資料建模的影響
在深入探討特定模式之前,理解網路邊界所帶來的限制至關重要。在單體架構中,外鍵約束可確保參考完整性。但在分散式系統中,網路延遲與可能的分割意味著即時一致性通常無法實現,或成本過高。
- 網路分割: CAP定理指出,在網路分裂的情況下,您必須在一致性與可用性之間做出選擇。
- 資料所有權:服務必須擁有其資料以避免緊密耦合。這限制了跨服務邊界直接的外鍵關係。
- 交易邊界:由於效能與可靠性風險,通常不鼓勵跨多個資料庫的全域交易。
在為此環境建立ERD時,圖表必須反映邏輯關係,而不僅僅是物理限制。視覺化表示需要清楚傳達資料存放的位置以及如何進行同步。
🔗 無外鍵情況下的參考完整性管理
在分散式交易系統中,物理外鍵通常不存在。相反,邏輯關係透過應用程式邏輯或非同步事件來強制執行。ERD必須清楚地捕捉這些邏輯連結。
1. 邏輯識別符參考
取代物理鍵約束,模型使用唯一識別符。繪製圖表時,應標示關係為邏輯連結。
- 使用虛線來表示邏輯依賴關係。
- 將關係標示為「參考」而非「約束」。
- 明確指定ID的資料類型,以確保結構中的類型安全性。
2. 軟性參考
在分散式系統中,硬刪除具有風險。常見模式是將記錄標記為已刪除,而非直接移除。ERD應包含狀態欄位。
- 包含一個
is_active或status欄位。 - 在圖表註解中記錄實體的生命周期。
- 明確說明在刪除事件中,孤立記錄如何處理。
3. 最終一致性建模
當資料在服務間複製時,一致性並非立即達成。ERD應視覺化複製延遲。
- 標記只讀複製的實體。
- 區分「真實來源」與「快取版本」。
- 指出用於同步變更的機制(例如,變更數據捕獲)。
⚡ 建模Saga模式
Saga模式是分散式交易的基石。它透過將交易拆分成一系列本地交易來管理長時間執行的操作。每個本地交易會更新特定服務中的資料,並觸發下一步。
1. 表示狀態機
由於Saga依賴狀態,ERD必須明確地建模流程的狀態轉移。
- 建立一個
SagaInstance實體。 - 定義如
INITIATED,COMPLETING,COMPENSATING,以及COMPLETED. - 將Saga實例連結至它所影響的特定業務實體。
2. 补偿交易
如果某一步驟失敗,Saga必須回滾先前的步驟。圖表應顯示反向關係。
- 為每一步驟記錄補償操作。
- 確保
SagaLog表格能記錄所有步驟的歷史。 - 將回滾路徑以獨立的關係線來視覺化。
3. 事件觸發
Saga通常由事件驅動。ERD需要顯示事件如何觸發狀態變更。
- 包含一個
事件日誌表。 - 將事件對應到特定的Saga狀態轉換。
- 指出哪些服務消耗哪些事件。
📊 比較一致性模式
理解不同一致性模型之間的權衡對於準確的ERD設計至關重要。下表概述了常見模式的特徵。
| 模式 | 一致性等級 | ERD複雜度 | 最佳使用情境 |
|---|---|---|---|
| 兩階段提交 | 強一致性 | 低 | 內部服務協調 |
| Saga編排 | 最終一致性 | 高 | 長時間運行的業務流程 |
| Saga協作 | 最終一致性 | 中等 | 鬆散耦合的微服務 |
| CQRS讀取模型 | 最終一致性 | 中等 | 高讀取負載 |
| 事件溯源 | 強一致性(每聚合) | 高 | 審計追蹤與狀態重建 |
🔄 命令查詢責任分離 (CQRS)
CQRS 將讀取模型與寫入模型分離。這表示寫入端的實體關係圖(ERD)將與讀取端的實體關係圖(ERD)有顯著差異。
1. 寫入模型設計
寫入模型專注於資料完整性與業務規則。
- 對資料進行正規化以減少冗餘。
- 在建立時強制執行嚴格的驗證規則。
- 保持資料結構嚴謹,以防止邏輯錯誤。
2. 讀取模型設計
讀取模型專注於效能與查詢速度。
- 反正規化資料以避免連接操作。
- 為常見查詢包含預先連接的欄位。
- 根據使用者介面需求而非邏輯來設計資料表結構。
3. 同步機制
實體關係圖(ERD)必須顯示寫入模型如何更新讀取模型。
- 使用投影實體來映射資料流。
- 記錄寫入與讀取可用性之間的延遲。
- 包含用於處理資料偏移的校正程序。
🗂️ 分片與分割金鑰
擴展通常需要將資料跨多個節點進行分片。實體關係圖(ERD)必須反映資料的分佈方式,以確保查詢效率。
1. 識別分片金鑰
分片金鑰決定資料由哪個節點儲存。
- 在實體定義中明確標示分片金鑰。
- 確保該金鑰經常出現在查詢中。
- 避免導致資料分佈不均的金鑰。
2. 跨分片關係
跨越分片的關係代價高昂。實體關係圖(ERD)應突出顯示這些關係。
- 為跨分片連結使用特定符號。
- 盡量減少跨越分片邊界的關係數量。
- 考慮反正規化以避免跨分片連接。
3. 全域索引與區域索引
索引策略會根據分片模型而有所不同。
- 本地索引對於單一分片查詢非常高效。
- 全域索引需要掃描所有分片,影響效能。
- 記錄哪些索引是本地的,哪些是全域的。
📜 事件溯源與不可變狀態
事件溯源將實體的狀態儲存為一系列事件。這改變了ERD表示實體本身的方式。
1. 事件儲存庫
主要實體變成了事件日誌。
- 建立一個
事件流表。 - 儲存如
事件ID,時間戳,以及聚合ID. - 確保負載以結構化資料形式儲存。
2. 聚合
聚合是觸發事件的根實體。
- 將聚合ID連結至事件流。
- 不要將目前狀態儲存為欄位。
- 透過重播日誌中的事件來重建狀態。
3. 快照
為了優化效能,可以儲存目前狀態的快照。
- 建立一個
快照表。 - 將快照連結至聚合ID。
- 記錄快照的版本號。
🛡️ 常見陷阱與反模式
即使使用先進的模式,仍可能出錯。識別反模式有助於維持系統健康。
- 緊密耦合:避免直接引用其他服務的實體。改用 ID。
- 循環依賴:若實體 B 依賴實體 A,則確保實體 A 不依賴實體 B。
- 過度規範化:在讀操作密集的系統中,過度規範化會導致性能下降。
- 忽略時區:分散式系統在全球運作。請以 UTC 儲存時間戳。
- 遺漏冪等性:確保操作可重試且不會產生副作用。
🔄 模式演進與版本控制
分散式系統的演進速度遠快於單體系統。ERD 必須支援模式變更,而不會破壞現有的服務。
1. 向後相容性
模式的變更不得破壞消費者。
- 僅可新增欄位,切勿立即移除或重命名現有欄位。
- 逐步淘汰欄位。
- 與模式一同為 API 合約版本化。
2. 迁移策略
在生產環境中處理資料遷移需要謹慎。
- 部署時使用擴展與收縮模式。
- 確保過渡期間舊的模式仍可讀取。
- 記錄失敗遷移的回滾計畫。
🖼️ 可視化跨服務依賴
標準的 ERD 展示單一資料庫中的資料表。分散式 ERD 必須展示服務。
1. 服務邊界
根據擁有資料表的服務來分組。
- 為每個服務使用獨立的容器。
- 使用服務名稱標記容器。
- 使用箭頭顯示容器之間的資料流。
2. 資料流
標示資料如何在服務之間移動。
- 使用實線表示同步呼叫。
- 使用虛線表示非同步事件。
- 標示資料流的方向。
3. 整合點
識別服務互動的位置。
- 在圖中突出顯示 API 網關。
- 將訊息代理標示為中介者。
- 記錄每個整合所使用的協定。
🏁 系統設計師的最終考量
為分散式交易設計是一種管理複雜性的練習。ERD 是一種將此複雜性傳達給團隊的工具。它不僅應顯示表格,還應展現系統的邏輯。
- 著重於邏輯關係,而非物理限制。
- 為每個關係記錄一致性保證。
- 為資料模型中的失敗情境進行規劃。
- 隨著系統的演進,持續更新圖表。
遵循這些模式,您將建立一個支援高可用性與資料完整性的藍圖。圖表將成為一份活文件,引導開發與維護工作。











