最佳事件采购数据库战略

问题描述 投票:24回答:6

我想设置一个小型的事件采购库。我在网上阅读了一些教程,到目前为止一切都被理解了。

唯一的问题是,在这些不同的教程中,有两种不同的数据库策略,但没有任何注释,为什么他们使用他们使用的那个。

所以,我想问你的意见。重要的是,为什么您更喜欢您选择的解决方案。

  1. 解决方案是db结构,您可以在其中为每个事件创建一个表。
  2. 解决方案是db结构,您只需创建一个通用表,并将事件作为序列化字符串保存到一列。

在这两种情况下,我都不确定它们如何处理事件更改,也许它们会创建一个全新的事件。

亲切的问候

database cqrs event-sourcing
6个回答
34
投票

我建立了自己的事件采购库,我选择了选项2,这就是原因。

  • 您可以通过聚合ID而不是事件类型来查询事件流。
  • 如果事件全部在不同的表中,则按顺序重现事件将是一种痛苦
  • 这会使升级事件变得有点痛苦

有一种说法可以说你可以在每个聚合上存储事件,但这取决于项目的要求。

我确实有一些关于如何使用事件流的帖子,你可能会觉得有用。


13
投票

解决方案是db结构,您只需创建一个通用表,并将事件作为序列化字符串保存到一列

这是迄今为止最好的方法,因为重放事件更简单。现在我在事件采购方面的两分钱:这是一个很好的模式,但你应该小心,因为不是一切都像看起来那么简单。在我正在研究的系统中,我们保存了每个聚合的事件流,但是我们仍然有一组规范化的表,因为我们无法接受为了获得对象的最新状态,我们必须运行所有事件(快照有帮助,但不是一个完美的解决方案)。因此,事件来源是一个很好的模式,它为您提供了完整的实体版本和完整的审计日志,它应该仅用于此,而不是作为一组规范化表的替代,但这只是我的两个美分。


4
投票

我认为最好的解决方案是选择#2。如果您使用像mysql这样的事务性数据库,甚至可以同时将当前状态与相关事件一起保存。

我真的不喜欢并推荐解决方案#1。

如果您对#1的关注是关于事件版本控制/升级;然后为每个新变更声明一个新类。不要太懒惰;或者重复使用。让订阅者了解变化;给他们活动版。

如果您对#1的关注与查询/解释事件有关;之后您可以随时轻松地将事件推送到nosql db或eventstore(从原始数据库)。

也;我用于事件采购库的模式是这样的:

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. 基于你的用例: 一个。在聚合表上创建和注册,生成ID,版本= 0和事件类型,并在事件表上创建事件; 湾按聚合表检索,按ID或事件类型检索事件,应用业务案例,然后更新聚合表(版本和事件类型),然后在事件表上创建事件。

虽然我这种方法更新了聚合表上的某些字段,但它只将事件表保留为附加,并提高了性能,因为在聚合表中有最新版本的聚合。


0
投票

我会选择#2,如果你真的希望通过事件类型有一种有效的搜索方式,我只想在该列上添加一个索引。


0
投票

以下是访问本案涉及的主题数据的两种策略。 1)当前状态和2)事件排序。在当前状态下,我们处理事件但仅保留主题的最后状态。通过事件排序,我们通过在每次需要状态时处理事件来保留事件并重建当前状态。事件排序更可靠,因为我们可以跟踪导致当前状态的所有事件,但它绝对没有效率。保持中间状态(快照)不仅是最后一个,以避免始终重新处理所有事件,这是常识。现在我们拥有可靠性和性能。

在加密货币中有事件排序和本地快照 - 名称中的本地是因为区块链是分布式的并且数据是复制的。

© www.soinside.com 2019 - 2024. All rights reserved.