咱們在看 Domain-Driven Design 的書或資料時,應該三不五十會看到 CQRS 這個東西,並且後來如果又單獨查了 CQRS 的東西,就又會有不同的用法,所以這裡我們就來理一下這些東西。
上面這張架構圖基本上應該是我們最常看到的 Event Sourcing + CQRS 的架構圖,我先來簡單說一下它的流程 :
然後接下來 query 的情境就幾乎和我們一般的使用情況差不多了。
然後這裡來說說它的起源與優缺。
Event Sourcing 嚴格來說是從 DDD 有後才比較有名的產物,它的概念就是 :
我們資料庫只存 Domain Event,而不是我們傳統的 Domain State ( 就是資料庫存當下狀態 )
因為在 DDD 中的 Aggregate 的變化都是會產生 Domain Event,所以我們是不是只有留下他就可以產出最後的 State 了 ?
那這樣有什麼好呢 ?
備註:
第 3 點可以用我們之前談過的 transactional outbox 來處理。
Day-23: Domain Event 之 Transactional OutBox 與 EventBus
因為每一次拿狀態都要抓一堆 Domain Event 來回復 State 啊,所以這裡通常會配 CQRS
我們大部份的產品服務正常情況下一定是 Query > Command 的情境,所以如果沒這樣用,那它應該早就因為 latency 太高,而且罵到爆了,或倒閉了。
簡單的說要花很多時間處理,一切都是挑戰,但要想想你得到了什麼。
這個也算是 CQRS 的應用一種,就是將模型分成 :
會有這個的原因在於 :
Aggregate Model 在 Query 情境下,很耗資源,而且那些欄位也不一定是 Query 需要的
然後這種模式還有個好處 :
所以事實上我看過不少人在架構設計上都是用這種方式的,例如這個 youtube 中提到的架構,它也是在 application 那層分開來。
但這裡是有幾個東西要想一下 :
我自已覺得可以。
然後通常會碰到的第一個問題就是,如果我需要先讀資料來做判斷,但讀 read 那台會有延遲,要如何處理 ?
那就讀寫的那台 db,而且目前很多資料庫 libary 都也有支援讀寫分離。
我這裡想法是類似在程式碼中有個很像 aggregate 的 query model,然後它會對映到 db 的 view,因為這樣就可以透過 db 只抓 model 中需要的欄位,所以嚴格說來那個 query model 比較接近 scheam。
可以使用 baseModel,但要記得那個 model 只能支援讀的東西,不然會讓 query model 變成可以修改東西的 model。
就直接在 usecase 或 service 抓取那個 view 吧,但也不是說不能在 query 那裡多個 repository,但就只是它回傳的是 query model,但我自已比較少看過。
在實務上大部份是以第二種為主,目前我真的比較少看過實際有使用 Event Sourcing + CQRS 來當一個公司的基礎架構上,有聽過的也只是當小專案實驗用,所以我沒很詳細說 Event Sourcing 也是這個原因。
這裡要不要使用就自已判斷吧,但如果是我應該不會將第一種方案當標配,基本上會從第二種方案來開始考慮。