2015-02-23 62 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,如果你真的想通过事件类型搜索有效的方式,我只需要在该列上添加一个索引。