場景
設想正在使用微服務架構(gòu)模式開發(fā)一個在線商店應用。大多數(shù)服務需要持久化數(shù)據(jù)到某種類型的數(shù)據(jù)庫中。例如,訂單服務存儲訂單相關(guān)信息以及用戶信息存儲用戶相關(guān)信息。

問題
微服務應用中的數(shù)據(jù)庫架構(gòu)是什么樣的?
約束條件
服務必須是松耦合的,這樣才能夠獨立地開發(fā)、部署和擴展這些微服務。
必須保持某些跨多個服務的業(yè)務事務的不變性。例如,下訂單用例必須驗證新訂單不會超出用戶信用額度限制。某些業(yè)務事務必須更新由多個服務擁有的數(shù)據(jù)。
某些業(yè)務事務需要查詢由不同服務擁有的數(shù)據(jù)。例如,查看可用信用額度用例必須查詢用戶服務來查找信用額度限制以及訂單服務來計算未完成訂單總數(shù)量。
某些查詢必須關(guān)聯(lián)由多個服務擁有的數(shù)據(jù)。例如,查找屬于特定區(qū)域的用戶以及他們最近一段時間的訂單,需要關(guān)聯(lián)用戶和訂單。
有時候為了擴展,數(shù)據(jù)庫必須可以被復制和共享。
不同服務有不同的數(shù)據(jù)存儲要求。對于某些服務,關(guān)系型數(shù)據(jù)庫是最好的選擇。其它服務可能需要NoSQL數(shù)據(jù)庫比如MongoDB(擅長存儲復雜、非結(jié)構(gòu)化數(shù)據(jù))或Neo4J(能高效地存儲以及查詢圖形數(shù)據(jù))。
解決方案
使用被多個服務共享的單個數(shù)據(jù)庫。每個服務自由地使用本地ACID事務訪問由其它服務擁有的數(shù)據(jù)。
實例
訂單服務和用戶服務自由地訪問彼此的表。例如,訂單服務能夠使用下面的ACID事務來確保某個新訂單不會違反該用戶的信用額度限制。
BEGIN TRANSACTION
....
SELECT ORDER_TOTAL FROM ORDERS WHERE CUSTOMER_ID = ?
....
SELECT CREDIT_LIMIT FROM CUSTOMERS WHERE CUSTOMER_ID = ?
....
INSERT INTO ORDERS ....
....
COMMIT TRANSACTION
數(shù)據(jù)庫將會保證信用額度不會超出即使當同步的事務嘗試去為相同的用戶創(chuàng)建訂單時。
影響
該模式的好處:
開發(fā)人員可以使用熟悉的和簡單明了的ACID事務來實施數(shù)據(jù)一致性。
單個數(shù)據(jù)庫比較容易操作。
該模式的弊端:
開發(fā)時間上的耦合 —— 某個開發(fā)人員致力于,例如,訂單服務,會需要與其它服務訪問相同表的開發(fā)人員協(xié)調(diào)schema相關(guān)更改。
運行時耦合 —— 因為所有的服務訪問相同的數(shù)據(jù)庫,他們可能會互相干擾。例如,如果長時間運行的用戶服務事務保有在ORDER表上的某個鎖,那么訂單服務將會被阻塞。
單個數(shù)據(jù)庫可能不會滿足所有服務的數(shù)據(jù)存儲和訪問的需求。