本文我們聊聊 CQRS 這種架構模式。
CQRS 是用來解決什么問題的?
我們先看一個場景。
系統中的數據模型是按照實體以及關系進行設計的是吧。
例如電商系統,包含訂單、用戶、商品等等數據。
數據的變更操作、查詢操作,都是基於這一套數據模型的。
但是,實際場景下的查詢需求是多種多樣。
例如這3類人群:
-
商家
-
買家用戶
-
電商運營人員
他們的數據視角是不同的,各自的關注角度不同,需要查詢的數據就完全不同。
但數據模型是一套啊,怎么辦?
是不是就需要做數據關聯、構建臨時數據集合等等復雜的操作啊。
基於一種數據模型,來實現 N 種視角的查詢,既別扭又麻煩。
CQRS 是怎么解決的呢?
CQRS 的全稱是:
Command Query Responsibility Segregation
意思是 命令查詢職責隔離。
命令是指 插入、修改、刪除,就是更改數據的動作。
隔離之后,結構就變成了這樣:
所以,CQRS 會有兩個數據模型,一個命令模型,一個查詢模型(可以有多個)。
命令模型的數據變更后,需要同步給查詢模型。
這樣做的核心目的就是:
讓數據查詢可以放飛自我。
各種復雜的查詢操作再也不用基於單一死板的存儲結構了。
命令模型數據同步過來之后,查詢模型可以根據自己的想法來重新組織數據結構,從而實現想怎么查就怎么查,簡單高效。
這樣就解決了以前單一數據模型帶來的查詢尷尬場面。
這看起來不就是變成2個微服務嗎?
並不是的,微服務的划分是基於業務領域的,不同的領域才划分為不同的微服務。
但 CQRS 中的命令模型、查詢模型,它們還是屬於同一領域的,查詢模型不能脫離命令模型,它們是緊耦合的。
所以 CQRS 並不是兩個獨立的微服務。
那么 CQRS 如何同步數據呢?
這是沒有限定的,你可以使用同步更新。
也可以異步更新,例如使用 MQ。
這種方式用的比較多,因為它的可靠性、擴展性都很好,只是會有短暫的數據不一致。
CQRS 看起來很像緩存啊?
是有些類似,但查詢模型並不是單純的用來提升查詢性能的數據鏡像。
查詢模型的本質是用於創建多樣化的數據展現形式。每一種形式適用於某類用戶的需求。
CQRS 的查詢模型可以使用不同的技術實現,例如有些使用關系數據庫,有些使用 Redis ……
CQRS 把數據變更、查詢分離之后,為查詢帶來了最大化的自由,同時呢,也大幅提升了這兩方面的工作效率,相較於之前整合在一起,分開后負載壓力肯定會減輕。這也是 CQRS 帶來的性能優勢。
CQRS 有什么不足?
凡事都有兩面性,很明顯,CQRS帶來了復雜性。
之前一體的時候,只有一個數據模型,一套技術。
使用 CQRS 之后,至少就要有 2 個模型,使用的技術也會增加。
還要保持數據的同步,開發維護的任務自然更重了。
還有數據一致性的問題,如果使用同步方式,一致性強,但跨數據源的實時同步可不容易,寫入性能必然下降,失敗的概率也會增加。
如果使用異步方式,那就要考慮數據延遲問題,在需要立即看到變化結果的場景就不能使用了。
小結一下,CQRS 把數據的變更和查詢拆開了,有各自的數據模型。
命令模型負責數據的變更,並把最新數據同步給命令模型。
命令模型根據自己的想法來安排數據,想怎么用就怎么用。
好處是可以讓查詢更加自由,更快的滿足多變的業務需求。
壞處是增加了架構的復雜度,還有數據同步帶來的問題。
我們可以根據自己的實際情況來抉擇。
推薦閱讀