我一直在閱讀關於CQRS+EventSoucing
模式(我希望在不久的將來應用)以及我發現的所有套牌和演示文稿共同的一點是爲了恢復您的模型狀態它,但沒有一個共享這樣做的模式/策略。快照獲取和恢復策略
我不知道你能否分享您在這個問題上的想法和經驗,特別是在以下方面:
- 何時快照
- 如何建模的快照存儲
- 應用/緩存冷啓動
TL; DR:您是如何在CQRS+EventSourcing
應用程序中實施Snapshotting
的?優點和缺點?
我一直在閱讀關於CQRS+EventSoucing
模式(我希望在不久的將來應用)以及我發現的所有套牌和演示文稿共同的一點是爲了恢復您的模型狀態它,但沒有一個共享這樣做的模式/策略。快照獲取和恢復策略
我不知道你能否分享您在這個問題上的想法和經驗,特別是在以下方面:
TL; DR:您是如何在CQRS+EventSourcing
應用程序中實施Snapshotting
的?優點和缺點?
確實需要快照的例子很少。但有一對夫婦 - 一個常見的例子是賬本中的賬戶。您可能會有數千或數百萬的信用卡/借記卡事件產生帳戶的最終狀態 - 如果每隔一段時間都快照一次,那就太瘋狂了。
我的方法來snapshoting當我設計Aggregates.NET是它的默認關閉,並讓您的聚集或實體必須從AggregateWithMemento
或EntityWithMemento
這反過來你的實體必須定義一個RestoreSnapshot
,一個TakeSnapshot
和ShouldTakeSnapshot
的繼承決定是否拍攝快照取決於實體本身。常見模式是
Boolean ShouldTakeSnapshot() {
return this.Version % 50 == 0;
}
哪個當然會每50個事件拍快照。
當讀取實體流時,我們所做的第一件事是檢查快照,然後從拍攝快照的瞬間讀取實體流的其餘部分。 IE:不要要求整個流只是我們沒有進行快照的部分。
至於商店 - 你可以直接使用任何東西。 VOU是正確的,雖然一個鍵值存儲是最好的,因爲你只需要1.檢查是否存在2.加載整個東西 - 這是理想的kv
對於系統重新啓動 - 我並不真正遵循你的上述問題是。沒有理由讓您的域名服務器處於有狀態,因爲它在不同的時間點做了不同的事情。它應該只做1件事 - 處理下一個命令。在處理命令的過程中,它從事件存儲裝載數據(包括快照),針對產生業務異常的實體或向商店記錄的域事件運行命令。
我想你可能會試圖通過這個關於緩存和冷啓動的討論來優化太多。
快照事件源模型是性能優化。性能優化的第一條規則?別。
具體來說,快照可以減少存儲庫中嘗試從事件存儲中重新加載模型歷史記錄所損失的時間。
如果您的存儲庫可以將模型保存在內存中,那麼您將不會經常重新加載它。所以從快照中獲得的勝利將很小。所以:不要。
如果你可以將你的模型分解爲aggregates
,也就是說你可以將模型的歷史分解成多個具有非重疊歷史的實體,那麼你的一個模型長模型歷史將變成很多很短的歷史每個描述對單個實體的更改。您需要加載的每個實體歷史記錄都非常短,所以從快照中獲勝將很小。所以:不要。
我今天工作的那種系統需要高性能,但不是24x7的可用性。因此,在我關閉系統維護並重新啓動的情況下,我不得不加載和重新處理所有事件存儲,因爲我的新系統不知道處理事件的聚合ID。我需要一個更好的起點,讓我的系統重新啓動更高效。
當存儲庫內存緩存很冷時,您擔心缺少寫入SLA,並且您有很長的模型歷史記錄以及大量要重新加載的事件。在嘗試將模型歷史重構爲更小的流時,使用快照技術可能會更合理。確定....
快照存儲區是一個讀取模型 - 在任何時間點,您應該能夠吹走模型並從事件存儲中的持續歷史中重建模型。
從存儲庫的角度來看,快照存儲是一個緩存;如果沒有快照可用,或者商店本身沒有在SLA內作出響應,則希望從初始種子狀態開始重新處理整個事件歷史記錄。
服務提供者接口是要看起來像
interface SnapshotClient {
SnapshotRecord getSnapshot(Identifier id)
}
SnapshotRecord是要提供到存儲庫,它需要消耗快照的信息。這是怎麼回事至少
該模型將然後重新水合物從紀念的快照狀態,從事件存儲,掃描向後載入歷史(即,從最近的事件開始)尋找在SnapshotRecord記錄的事件,然後按順序應用後續事件。
的SnapshotRepository本身可能是一個key-value存儲(在任何給定的ID最多一個紀錄),但與BLOB支持關係型數據庫將工作也沒關係
select *
from snapshots s
where id = ?
order by s.total_events desc
limit 1
快照投影機和存儲庫是緊密耦合 - 他們需要就所有可能的歷史事件的狀態應該達成一致,他們需要同意如何解除/重新保存紀念品,並且他們需要同意使用哪個ID來定位快照。
緊密的耦合也意味着您不需要特別擔心備忘錄的 模式;一個字節數組將會很好。
然而,他們並不需要同意他們以前的身份。快照投影機2.0丟棄/忽略快照投影機1.0留下的任何快照 - 快照存儲爲畢竟只是一個緩存。
我設計的應用程序可能會每天產生數百萬個事件。我們能做些什麼,如果我們需要重建一個視野6個月後
這裏的一個更令人信服的答案是時間明確建模。你有一個生命六個月的實體嗎?或者你有一百八十個實體每個生活一天?會計是一個很好的領域,在這裏可以參考:在財政年度結束時,這些書籍已經關閉,並且明年的書籍會隨着結轉而被打開。
Yves Reynhout經常談論建模時間和調度; Evolving a Model可能是一個很好的起點。
我今天工作的那種系統需要高性能,但不是24x7的可用性。因此,在我關閉系統維護並重新啓動的情況下,我不得不加載和重新處理所有事件存儲,因爲我的新系統不知道處理事件的聚合ID。我需要一個更好的起點,讓我的系統重新啓動更高效。 – Mikhas
如果你不保留所有的歷史記錄會怎樣?實際上,我正在設計一款應用程序,一天可能會產生數百萬件事件。如果我們需要在6個月後重建視圖,我們可以做些什麼?你能提供一些建議嗎? –
查看編輯以及Reynhout的演講。 – VoiceOfUnreason