CQRS-一種讀寫分離的資料處理模式
譯者按:
本文是翻譯自Martin Fowler的一篇部落格。
老馬同志向來是我所敬仰的大師級人物,現在的“微服務”這個詞就是從老馬同志的部落格開始火起來的。
原文連結
CQRS
CQRS指的是命令查詢職責分離模式,最早我聽 Greg Young 提起過,該模式的核心思想是把資料的讀操作和寫操作分離開來。在某些場景下這種模式很有用,但 CQRS 也會增加系統的複雜性。
大多數情況下人們把資訊系統作為可以進行增、刪、改、查的資料儲存庫。我們可以在記錄結構的 mental model 上進行建立、檢視、更新和刪除。所有這些活動可以被概括成兩類:儲存和檢索。
當需求變複雜時,CRUD 模式就顯示出了不足。我們可能想用特殊的方式檢視記錄:比如說把多條記錄合併為一條;或把不同地方的記錄整合為一條虛擬記錄。而實際操作時限制重重,通常情況下我們只能進行特定資料的合併,甚至有時儲存起來的資訊跟我們提供的根本不一致。
我們會接觸到很多資訊形式。當用戶進行操作時所面對的資訊的變現形式是不一樣的,而這些不同的形式代表的是同樣的資訊。開發人員通常使用操作模型的核心元素來構建概念模型。如果一個人在使用 Domain Model,那 Domain Model 就是他心目中 domain 的概念展示,同時,他也會盡可能的讓永續性儲存更接近整個概念模型。
這種多層表現形式的結構十分複雜,但對單個個體來說,他使用的是單一的概念模型,但這個概念模型其實代表了所有變現形式的整合。
CQRS 把傳統概念模型中的更新和檢視區分開來,就是我們熟知的 Command(命令)和 Query(查詢)。在很多情境下,尤其是領域模型比較複雜時,命令和查詢使用同一個模型很容易出現問題。
模型分離意味著不同的物件模型、不同的邏輯流程甚至是獨立的硬體。web 應用使用查詢模型來顯示正在進行訪問的使用者。如果使用者發出命令,命令會被傳輸到獨立的命令模型進行處理,然後由獨立的查詢模型來展示最新狀態。
這樣操作空間就很大了。當這兩個模型把一個數據庫作為通訊橋樑時,記憶體模型也可以共享這個資料庫。當然,它們也可能使用單獨的資料庫,查詢端就可以使用實時的 ReportingDatabase(報告資料庫)。在這種情況下,這兩個模型或它們的資料庫之間需要建立通訊機制。
這兩個模型可能會共用物件模型,然後物件模型對命令端和查詢端提供不同的介面,就像關係資料庫檢視一樣。但通常情況下的 CQRS,都是使用獨立模型。
CQRS 對其他一些體系結構模式也適用。
• 我們可以很容易地從基於 CRUD 模式的使用者交互向基於任務的使用者互動轉變。
• CQRS 非常適合基於事件的程式設計模型。CQRS 系統中分離的服務與 Event Collaboration(事件協作)進行通訊是很常見的。 這些服務可以輕鬆使用 Event Sourcing。
• 模型分離對保持模型一致性的難度提出了質疑,進而提高了使用 eventual consistency(最終一致性)的可能性。
• 對很多域來說,大部分邏輯只有在更新資料時才會被呼叫,因此使用 EagerReadDerivation 簡化查詢端模型很有必要。
• 如果寫模型針對所有更新都會生成事件,讀模型可以採用 EventPosters 結構,把事件按 MemoryImages 的形式進行儲存從而避免大量資料庫互動。
• CQRS也適用於複雜領域,Domain-Driven Design 可以提供更多幫助。
什麼時候可以考慮 CQRS
CQRS並不適用於所有場景,只適用於某些特定的場景。大部分系統都使用傳統的 CRUD 模式,人們對它的認知度也更高。CQRS 模式對人們來說跨度太大,所以說除非它成效顯著,不然很少有人願意去嘗試。雖然我見過 CQRS 的成功案例,但目前為止,CQRS 大多數情況下的執行不盡人意,人們認為使用 CQRS 會讓軟體系統出現問題。
CQRS 可以被應用到某些系統的特定部分(就像 DDD 中的 BoundedContext),而不應該被應用到整個系統。每個 Bounded Context 都需要決定如何建模。
目前來說,CQRS 在兩個方面的應用很好。首先,CQRS 可以輕鬆處理複雜場景。然而我想強調一下,這種情況是非常少的。通常情況下,命令和查詢重疊較多,共用一個模型更簡單些。如果 CQRS 和場景不匹配就會增加系統的複雜性,因此降低生產效率、增加風險。
CQRS 在高效能應用方面用處很大。CQRS 對讀取和寫入分開考慮。如果應用程式讀取和寫入比例差距較大,採用 CQRS 就很合適。即使不採用這種模式,你也要為讀取和寫入採取不同的優化策略。舉個例子:使用不同的資料庫訪問技術進行讀取和更新。
如果你的場景不適合使用 CQRS,但你又面臨查詢所帶來的複雜性或效能問題,可以嘗試一下 ReportingDatabase。CQRS 中所有查詢都使用單獨的模型,採用 reporting database 後,大部分查詢仍使用原系統,而那些特殊要求的查詢則由 reporting database 處理。
儘管好處眾多,但在使用 CQRS 時仍需謹慎。大多數資訊系統的讀寫方式是相同的,應用 CQRS 會增加系統的複雜性。我也見過某些案例,在應用 CQRS 後反而降低了生產效率、增加了專案不必要的風險。因此,CQRS 雖然是很好的工具,但也要小心使用,否則會適得其反。
延伸閱讀
• Greg Young was the first person I heard talking about this approach - this is the summary from him that I like best.
• Udi Dahan is another advocate of CQRS, he has a detailed description of the technique.
• There is a CQRS info site that Greg set up. Its documents section contains some interesting material.
• There is an active mailing list to discuss the approach.
• Greg Young is working on a book on CQRS.