3種CQRS架構模式

命令/查詢分離(CQS)

1988 年,Bertrand Meyer 在面向對象的軟件設計一書中設計了 CQS 原則。簡單來說,這個原則是說程序應當要麼修改系統(Command),要麼返回查詢結果(Query),軟件中應當保持命令與查詢的分離。

儘管 Martin Fowler 在他 2005 年的博客文章中也提到,這種分離並非總是可能的,一個很好的例子是返回一個剛插入的記錄的 id。首先,你要把記錄持久化(Command),其次,你要獲得它新分配的 id(Query)。

CQRS 架構

CQRS 建議將應用程序層分爲兩個方面,即命令端(Command)和查詢端(Query)。

查詢端負責優化讀取數據。從持久化獲取數據,然後將它們映射到展現層表單,這些表單通常被標識爲數據傳輸對象(DTO)。

命令端關注優化寫入數據。命令執行各種用例,修改實體狀態並將其持久化。

通過分離讀寫操作,我們提高了性能,並在系統中支持關注點分離原則。

本文介紹 3 種主要的 CQRS 架構實現。

單數據庫 CQRS

單一數據庫CQRS 模式沒有正式名稱,Mattew Renze 在他的課程Clean Architecture 中將其命名爲單一數據庫 CQRS,我也選擇這個命名。

顧名思義,雙方都在和一個數據庫對話。Command 在域中執行用例,從而修改實體的狀態,然後通過 ORM 如 Entity Framework Core 或 Hibernate 將實體保存到數據庫中。

Query 直接通過數據訪問層執行,數據訪問層要麼是使用各種 ORM,要麼通過存儲過程。

雙數據庫 CQRS

在“雙數據庫”方式中,我們需要兩個數據庫,一個用於寫操作,一個用於讀操作。命令端使用針對寫操作優化的數據庫。查詢端使用針對讀取操作優化的數據庫。

命令每改變一個狀態,修改後的數據就必須從寫數據庫推送到讀數據庫中,或者作爲一個跨兩個數據庫的分佈式事務,或者使用最終一致性模型。

這種架構給軟件的查詢端帶來了數量級的性能提升,這是有利的,因爲一般系統在讀數據上花費的時間一般比寫數據要更多。

事件源 (Event source) CQRS

最後一種是最複雜的 CQRS 架構。與前面兩種方式相比,事件源存儲數據的思路完全不同。

在事件源方法中,我們並不只存儲實體的當前狀態,而且將實體發生的每一個狀態作爲快照來存儲。實體並不是以標準化數據的形式保存,而是通過事件的時間戳來保存它們的變更。

事件源帶有以下好處:

  • 事件存儲包括完整的審計跟蹤,可以在需要嚴格監管的場景中派上用場。
  • 可以在任何時間點重建任何實體的任何狀態,這對於調試非常有用。
  • 可以重放事件,查看系統中任何時候到底發生了什麼。這個功能對於壓力測試和 bug 修復非常有用。
  • 可以輕鬆地重建生產數據庫。
  • 有多個爲讀優化的數據存儲。

但在另一方面,這種方式實現很複雜,如果你不能從其中受益,那麼用這個模式可能適得其反。

小結

CQRS 真正的威力在於可以對寫和讀操作進行不同的優化。但在另一方面,系統會變得更加複雜,命令端和查詢端代碼不完全一致。並且由於存在多個數據庫,管理更復雜,需要更繁瑣的 ORM 映射。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章