2017-08-30 48 views
4

我們已經構建了一個基於CQRS的系統,使用關係數據庫在域側和NoSQL DB在讀取側。領域方面遵循經典的關係方法,而讀方是非規範化的。 使用命令處理程序發出的事件完成數據複製和轉換。CQRS:更新不帶事件源的讀取模型

我有一個關於讀取端同步的兩個問題:

  • 什麼是使用的域端的關係數據完全重建閱讀模式的最佳方式?

    我們假設讀取模型不同步。 但即使它始終處於同步狀態,也可能需要導入測試數據庫 或執行一些批量操作。所以人們可能希望 從現有的寫入模型運行系統,而沒有相應的同步讀取模型。由於我們不使用事件採購,因此不存在重播所有事件的方式。

    我目前考慮一個ReadModelBuilder,它基本上做一個 SELECT * FROM在每個表上,並將每個實體轉換爲讀取端 表示。但是這會引入冗餘。 ReadModelBuilder需要知道轉換是如何完成的。 因此,在Command Handler執行一些寫入操作後,通常會執行讀取端同步 的事件處理程序。

    我想過放棄事件處理程序,並在每個類級別上用 取代同步機制。 例如而不是FooRenamedEventHandler重命名foo.name,它會調用FooReadModelBuilder,它將重寫完整的Foo 實例的 。 但我認爲這有弊端。在閱讀模型中,FooRenamedEventHandler可以更好地處理 以及foo.name的冗餘用法。

    UPDATE: 另一種方法可以讓ReadModelBuilder創建讀取模型實體將通過分割域實例爲事件,當順序執行,這將構建完整的讀端實體。 例如:

    Article域實體有一個Name和一個Price。 要構建讀取模型,ReadModelBuilder可以檢查域實體併發出ArticleCreatedEvent,ArticleRenamedEventArticlePriceChangedEvent。這樣,轉換邏輯將保留在事件處理程序中,但仍可從某種大容量複製機制調用。

    例如,ReadModelBuilders看起來是這樣的:

_

interface IReadModelBuilder<TEntity> 
{ 
    //// Returns a sequence of events which replicate the read-model 
    //// when executed by the event handlers. 
    Event[] GetReplicationSequence(TEntity instance); 
} 

UPDATE年底

_

  • 您通常如何檢測不同步的讀取模型?是否有一般的最佳做法?

在此先感謝您。

+0

這是一個有趣的問題。您有什麼情況可以避免同步? –

+0

我想任何嚴重軟件系統的高效使用都會遇到數據庫必須交換或批量轉換的情況。這可能是由軟件錯誤引起的。由於巴士系統中的錯誤。由於操作失敗。這可能是因爲有人可能想要部署測試數據庫。或者因爲必須部署較舊的備份。當然可以保留兩個數據庫作爲備份,但想象一下讀取端備份丟失或損壞。 – mbnx

+0

我明白了。如果你不堅持事件(即不使用事件源),那麼你不能輕易重建一個讀取模型。你的'重建者'必須以某種方式嘗試對寫模型進行逆向工程,並製造一些奇怪的事件,因爲寫模型甚至不能包含所有的信息,因爲它不需要它來完成他的工作 –

回答

0

如果您不堅持活動(即不使用Event sourcing),那麼您不能輕鬆重建read-model。您的Rebuilder必須以某種方式嘗試對寫模型進行逆向工程,並製作一些奇怪的事件,因爲write model甚至無法包含所有信息,因爲它不需要它來執行其工作。

所以,我的結論是,沒有event store或至少event log那麼你不能重建你的read-model。如果您有這樣的真相源,那麼您可以重建它,甚至通過使用持久性中所有處理過的事件ID列表來檢測不同步情況。

+0

謝謝。我想到了使用事件生成器的建議,該事件生成器對域進行反向工程。你是對的,事件可能包含域模型中未包含的數據。即使可以使用域數據進行計算,也可以在事件生成器和命令處理程序之間引入冗餘邏輯。此外,數據模式更改的實現複雜性也在增加,因爲數據庫上的每個新屬性都意味着事件生成器的擴展。似乎有某種事件日誌是唯一的選擇。 – mbnx