標籤:
命令查詢的責任分離Command Query Responsibility Segregation (簡稱CQRS)模式是一種架構體系模式,能夠使改變模型的狀態的命令和模型狀態的查詢實現分離。這屬於DDD應用領域的一個模式,主要解決DDD在資料庫報表輸出上處理方式。
Greg Young在infoQ的採訪中“State Transitions in Domain-Driven Design”談到了CQRS,Greg 解釋了把領域模型分為兩種:狀態校正,以及狀態轉換,維持目前狀態的一個視圖。
在用戶端就將資料的新增修改刪除等動作和查詢進行分離,前者稱為Command,走Command bus進入Domain對模型進行操作,而查詢則從另外一條路徑直接對資料進行操作,比如報表輸出等。
當一個Command進來時,從倉儲Repository載入一個彙總aggregate對象群,然後執行其方法和行為。這樣,會激發彙總對象群產生一個事件,這個事件可以分發給倉儲Repository,或者分發給Event Bus事件匯流排,比如JavaEE的訊息匯流排等等。事件匯流排將再次啟用所有監聽本事件的處理者。當然一些處理者會執行其他彙總對象群的操作,包括資料庫的更新。
因為領域對象操作和資料庫儲存持久這兩個動作分離,因此,資料表結構可以和領域對象松耦合(JiveJdon源碼可展示領域對象和資料表不再是一對一對應依賴,這也是使用Hibernate 等ORM架構容易造成的問題),你可以最佳化資料表結構專門用於查詢。
再者,由於事件驅動了領域模型的狀態改變,如果你記錄這些事件audit ,將可以將一些使用者操作進行回放,從而找到重要狀態改變的軌跡,而不是單純只能依靠資料表欄位顯示目前狀態,至於這些目前狀態怎麼來的,你無法得知。當你從資料庫中獲得彙總體時,可以將相關的事件也取出來,這些叫Event Sourcing,事件來源雖然沒有何時何地發生,但是可以清楚說明使用者操作的意圖。
雖然這種架構有些複雜,但是好處卻很多,主要的是實現透明的分散式處理Transparent distributed processing,當使用事件作為狀態改變的引擎時,你可以通過實現多任務並發處理,比如通過JVM並行計算或事件訊息匯流排機制,事件能夠很容易序列化,並在多個伺服器之間傳送,(EJB提倡貧血失血模型,實際就是為解決胖模型在多個伺服器之間傳送時序列化耗費效能,現在我們不序列化模型,而是改變模型資料的事件)。
[轉]命令查詢的責任分離 CQRS架構