2015-02-23 64 views
13

我想設置一個小事件採購庫。 我在網上閱讀了一些教程,到目前爲止所瞭解的一切。最佳事件採購數據庫策略

唯一的問題是,在這些不同的教程中,有兩種不同的數據庫策略,但沒有任何評論他們爲什麼使用他們使用的。

所以,我想問你的意見。 重要的是,爲什麼你更喜歡你選擇的解決方案。

  1. 解決方案是您爲每個事件創建一個表的數據庫結構。

  2. 解決方案是您只創建一個通用表的數據庫結構,並將事件作爲序列化字符串保存到一列。

在這兩種情況下,我不知道他們是如何處理事件的變化,也許他們創造了一個全新的。

親切的問候

回答

22

我建立我自己的事件採購lib和我選擇了選項2和這裏的原因。

  • 您可以通過聚合ID而非事件類型查詢事件流。
  • 再現順序的事件將是一個痛苦,如果他們都在不同的表
  • 這將使升級事件有些痛

有說你可以存儲在每個事件的說法總計但取決於項目的要求。

我確實有一些關於如何使用事件流的帖子,您可能會發現有幫助。

6 Code Smells With Your CQRS Events and How to Avoid Them

Aggregate Root – How to Build One for CQRS and Event Sourcing

How to Upgrade CQRS Events Without Busting Your Event Stream

我希望你覺得有用。

8

解決方案是創建只有一個通用的表,事件系列化串保存到一列

這是迄今爲止爲重放事件是簡單的,最好的辦法DB結構。現在我的事件採購的兩分錢:這是一個很好的模式,但你應該小心,因爲不是所有事情都像看起來那麼簡單。在我正在研究的系統中,我們保存了每個聚合的事件流,但是我們仍然有一組規範化的表,因爲我們無法接受爲了獲得對象的最新狀態,我們必須運行所有事件(快照有幫助,但不是一個完美的解決方案)。所以是的事件採購是一個很好的模式,它給你一個完整的實體版本和一個完整的審計日誌,它應該僅用於此目的,而不是替代一組規範化的表格,但這只是我的兩個美分。

+4

保持實體的最新(最終一致)視圖與事件採購不兼容,實際上它經常一起使用。事件採購只是意味着事件是數據的唯一權威來源,所以您的物化視圖/預測必須從中推導出來。將視圖視爲一種便利,隨時都可以被丟棄/重建,而且你很棒。 – AlexG 2017-05-26 11:16:46

+4

只要完成你的答案,不需要粗魯:) – AlexG 2017-05-29 16:51:34

+1

真的,這只是一種做CQRS的方式,它的設計圍繞着這樣的理解:在許多情況下,每次構建純事件都可能效率低下。 – 2017-10-12 18:40:01

3

我認爲最好的解決方案將與#2一起去。如果你使用像mysql這樣的事務性數據庫,甚至可以同時將當前狀態和相關事件保存在一起。

我真的不喜歡和推薦解決方案#1

如果您對#1的關注是關於事件版本控制/升級;然後爲每個新變更申報一個新班級。不要太懶;或者被重複使用所迷惑。讓訂戶瞭解變化;給他們的事件版本。

如果你的外表爲#1是關於類似查詢/解釋事件;那麼隨後您可以隨時輕鬆地將您的事件推送到nosqldb或事件庫(從原始數據庫)。

另外;我用於事件資源庫的模式是這樣的:

public interface IUserCreated : IEventModel 
{ 

} 

public class UserCreatedV1 : IUserCreated 
{ 
    public string Email { get; set; } 
    public string Password { get; set; } 
} 

public class UserCreatedV2 : IUserCreated 
{ 
    // Fullname added to user creation. Wrt issue: OA-143 

    public string Email { get; set; } 
    public string Password { get; set; } 
    public string FirstName { get; set; } 
    public string LastName { get; set; } 
} 

public class EventRecord<T> where T : IEventModel 
{ 
    public string SessionId { get; set; } // Can be set in emitter. 
    public string RequestId { get; set; } // Can be set in emitter. 
    public DateTime CreatedDate { get; set; } // Can be set in emitter. 
    public string EventName { get; set; } // Extract from class or interface name. 
    public string EventVersion { get; set; } // Extract from class name 
    public T EventModel { get; set; } // Can be set in emitter. 
} 

public interface IEventModel { } 

所以;使事件版本化和顯式升級;無論是在域和代碼庫中。在部署新事件的起源之前實現在訂閱者中處理新事件。和;如果不需要,不允許直接使用外部用戶的域名事件;把一個集成層或類似的東西。

我希望我的想法對你有用。

2

我讀到一個由以事件採購方法:具有兩個表

  1. :聚集體和事件;
  2. 根據你的使用情況:

    a。在聚合表上創建和註冊,生成ID,版本= 0和事件類型並在事件表上創建事件;

    b。從聚合表中檢索,按ID或事件類型檢索事件,應用業務案例,然後更新聚合表(版本和事件類型),然後在事件表上創建事件。

我雖然這種做法會更新彙總表的某些領域,它的葉子事件表作爲唯一的追加和改善服務表現,你有最新版本的合計表中的骨料。

0

我會去#2,如果你真的想通過事件類型搜索有效的方式,我只需要在該列上添加一個索引。