本文我們聊聊 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 把數據的變更和查詢拆開了,有各自的數據模型。
命令模型負責數據的變更,并把最新數據同步給命令模型。
命令模型根據自己的想法來安排數據,想怎么用就怎么用。
好處是可以讓查詢更加自由,更快的滿足多變的業務需求。
壞處是增加了架構的復雜度,還有數據同步帶來的問題。
我們可以根據自己的實際情況來抉擇。
推薦閱讀