database 最佳事件采购数据库策略

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/28667367/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 07:53:37  来源:igfitidea点击:

best event sourcing db strategy

databasecqrsevent-sourcing

提问by SharpNoiZy

I want to setup a small event sourcing lib. I read a few tutorials online, everything understood so far.

我想设置一个小事件源库。我在网上阅读了一些教程,到目前为止一切都明白了。

The only problem is, in these different tutorials, there are two different database strategies, but without any comments why they use the one they use.

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

So, I want to ask for your opinion. And important, why do you prefer the solution you choose.

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

  1. Solution is the db structure where you create one table for each event.

  2. Solution is the db structure where you create only one generic table, and save the events as serialized string to one column.

  1. 解决方案是 db 结构,您可以在其中为每个事件创建一个表。

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

In both cases I'm not sure how they handle event changes, maybe they create a whole new one.

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

Kind regards

亲切的问候

回答by Codescribler

I built my own event sourcing lib and I opted for option 2 and here's why.

我构建了自己的事件源库,并选择了选项 2,原因如下。

  • You query the event stream by aggregate id not event type.
  • Reproducing the events in order would be a pain if they are all in different tables
  • It would make upgrading events a bit of pain
  • 您按聚合 id 而非事件类型查询事件流。
  • 如果它们都在不同的表中,按顺序重现事件会很痛苦
  • 它会让升级事件有点痛苦

There is an argument to say you can store events on a per aggregate but that depends of the requirements of the project.

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

I do have some posts about how event streams are used that you may find helpful.

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

回答by MeTitus

Solution is the db structure where you create only one generic table, and save the events as serialized string to one column

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

This is by far the best approach as replaying events is simpler. Now my two cents on event sourcing: It is a great pattern, but you should be careful because not everything is as simple as it seems. In a system I was working on we saved the stream of events per aggregate but we still had a set of normalized tables, because we just could not accept that in order to get the latest state of an object we would have to run all the events (snapshots help but are not a perfect solution). So yes event sourcing is a fine pattern, it gives you a complete versioning of your entities and a full auditing log, and it should be used just for that, not as a replacement of a set of normalized tables, but this is just my two cents.

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

回答by Safak Ulusoy

I think best solution will be to go with #2. And even you can save your current state together with the related event at the same time if you use a transactional db like mysql.

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

I realy dont like and recommend the solution #1.

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

If your concern for #1is about event versioning/upgrading; then declare a new class for each new change. Dont be too lazy; or be obsess with reusing. Let the subscribers know about changes; give them the event version.

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

If your concers for #1is about something like querying/interpreting events; then later you can easily push your events to an nosqldb or eventstore at any time (from original db).

如果您对#1的顾虑是关于查询/解释事件;然后,您可以随时(从原始数据库)轻松地将您的事件推送到 nosqldb 或 eventstore。

Also; the pattern I use for eventsourcing lib is something like that:

还; 我用于事件源库的模式是这样的:

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 { }

So; make event versioning and upgrading explicit; both in domain and codebase. Implement handling of new events in subscribers before deploying origin of new events. And; if not required, dont allow direct consuming of domain events from external subscribers; put an integration layer or something like that.

所以; 使事件版本控制和升级明确;在域和代码库中。在部署新事件的来源之前,在订阅者中实现对新事件的处理。和; 如果不需要,则不允许直接使用来自外部订阅者的域事件;放置一个集成层或类似的东西。

I wish my thoughts will be useful for you.

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

回答by Felipe

I read about an event-sourcing approach that consists in:

我读到了一种事件溯源方法,其中包括:

  1. having two tables: aggregate and event;
  2. base on you use cases either:

    a. creates and registry on aggregate table, generating an ID, version = 0 and a event type and create an event on event table;

    b. retrieve from aggregate table, events by ID or event type, apply business cases and then update aggregate table (version and event type) and then create an event on event table.

  1. 有两个表:聚合和事件;
  2. 根据您的用例:

    一种。在聚合表上创建和注册,生成 ID,版本 = 0 和事件类型,并在事件表上创建事件;

    湾 从聚合表中检索事件,按 ID 或事件类型,应用业务案例,然后更新聚合表(版本和事件类型),然后在事件表上创建事件。

although I this approach updates some fields on aggregate table, it leaves event table as append only and improves performace as you have the latest version of an aggregate in aggregate table.

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

回答by Jacob Zimmerman

I would go with #2, and if you really want to have an efficient way of search via event type, I would just add an index on that column.

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

回答by user3783189

Here are the two strategies to access the data about a subject involved in this case. 1) current state and 2) event sequencing. With current state we process the events but keep only the last state of the subject. With event sequencing we keep the events and rebuild the current state by processing the events every time we need the state. Event sequencing is more reliable as we can track everything that happened causing the current state but it's definitely not efficient. It's a common sense to keep also intermediate states (snapshots) not only the last one to avoid reprocessing all the events all the time. Now we have reliability and performance.

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

In crypto currencies there are the event sequencing and local snapshots - the local in the name is because blockchains are distributed and data are replicated.

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