最佳事件采购数据库策略
best event sourcing db strategy
我想设置一个小型事件源库。
网上看了几个教程,到此为止都明白了。
唯一的问题是,在这些不同的教程中,有两种不同的数据库策略,但没有任何评论为什么他们使用他们使用的那个。
所以,我想征求一下您的意见。
重要的是,为什么您更喜欢您选择的解决方案。
解决方案是为每个事件创建一个 table 的数据库结构。
解决方案是只创建一个通用 table 的数据库结构,并将事件作为序列化字符串保存到一列。
在这两种情况下,我都不确定他们是如何处理事件变化的,也许他们会创建一个全新的。
亲切的问候
我构建了自己的事件源库并选择了选项 2,原因如下。
- 您通过聚合 ID 而非事件类型查询事件流。
- 如果事件都在不同的表中,按顺序重现事件会很痛苦
- 这会让升级事件有点痛苦
有人说您可以将事件存储在每个聚合上,但这取决于项目的要求。
我确实有一些关于如何使用事件流的帖子,您可能会觉得有用。
Solution is the db structure where you create only one generic table, and save the events as serialized string to one column
这是迄今为止最好的方法,因为重播事件更简单。现在我对事件溯源的两分钱:这是一个很好的模式,但你应该小心,因为并非一切都像看起来那么简单。在我正在处理的系统中,我们保存了每个聚合的事件流,但我们仍然有一组规范化表,因为我们无法接受为了获得对象的最新状态,我们必须 运行 所有事件(快照有帮助但不是完美的解决方案)。所以是的,事件溯源是一个很好的模式,它为您提供了实体的完整版本控制和完整的审计日志,它应该仅用于此目的,而不是作为一组规范化表的替代品,但这只是我的两个分.
我认为最好的解决方案是 #2。如果您使用像 mysql.
这样的事务数据库,甚至可以同时保存当前状态和相关事件
我真的不喜欢并推荐解决方案 #1。
如果您对 #1 的关注是关于事件 versioning/upgrading;然后为每个新更改声明一个新的 class。不要太懒惰;或者沉迷于重用。让订阅者知道变化;给他们活动版本。
如果您对 #1 的担忧与 querying/interpreting 事件有关;然后您可以随时轻松地将事件推送到 nosqldb 或 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 { }
所以;使事件版本控制和升级明确;在域和代码库中。在部署新事件的来源之前,在订阅者中实施新事件的处理。和;如果不需要,不允许直接使用来自外部订阅者的域事件;放置一个集成层或类似的东西。
希望我的想法对你有用。
我读到了一种事件溯源方法,它包括:
- 有两个 table:聚合和事件;
根据您的用例:
一个。在聚合 table 上创建和注册,生成 ID、版本 = 0 和事件类型,并在事件 table;
上创建事件
b。按 ID 或事件类型从聚合 table、事件中检索,应用业务案例,然后更新聚合 table(版本和事件类型),然后在事件 table.[=10 上创建事件=]
尽管我使用这种方法更新了聚合 table 上的某些字段,但它将事件 table 保留为仅附加并提高了性能,因为您拥有聚合的最新版本 table .
我会选择 #2,如果您真的想要一种通过事件类型进行搜索的有效方式,我会在该列上添加一个索引。
以下是访问本案所涉及主体数据的两种策略。
1) 当前状态和 2) 事件排序。
使用当前状态,我们处理事件但只保留主题的最后状态。
通过事件排序,我们保留事件并通过在每次需要状态时处理事件来重建当前状态。
事件排序更可靠,因为我们可以跟踪导致当前状态发生的所有事情,但它绝对效率不高。保留中间状态(快照)而不仅仅是最后一个状态是一种常识,以避免一直重新处理所有事件。现在我们拥有可靠性和性能。
在加密货币中有事件排序和本地快照——名称中的本地是因为区块链是分布式的,数据是复制的。
我想设置一个小型事件源库。 网上看了几个教程,到此为止都明白了。
唯一的问题是,在这些不同的教程中,有两种不同的数据库策略,但没有任何评论为什么他们使用他们使用的那个。
所以,我想征求一下您的意见。 重要的是,为什么您更喜欢您选择的解决方案。
解决方案是为每个事件创建一个 table 的数据库结构。
解决方案是只创建一个通用 table 的数据库结构,并将事件作为序列化字符串保存到一列。
在这两种情况下,我都不确定他们是如何处理事件变化的,也许他们会创建一个全新的。
亲切的问候
我构建了自己的事件源库并选择了选项 2,原因如下。
- 您通过聚合 ID 而非事件类型查询事件流。
- 如果事件都在不同的表中,按顺序重现事件会很痛苦
- 这会让升级事件有点痛苦
有人说您可以将事件存储在每个聚合上,但这取决于项目的要求。
我确实有一些关于如何使用事件流的帖子,您可能会觉得有用。
Solution is the db structure where you create only one generic table, and save the events as serialized string to one column
这是迄今为止最好的方法,因为重播事件更简单。现在我对事件溯源的两分钱:这是一个很好的模式,但你应该小心,因为并非一切都像看起来那么简单。在我正在处理的系统中,我们保存了每个聚合的事件流,但我们仍然有一组规范化表,因为我们无法接受为了获得对象的最新状态,我们必须 运行 所有事件(快照有帮助但不是完美的解决方案)。所以是的,事件溯源是一个很好的模式,它为您提供了实体的完整版本控制和完整的审计日志,它应该仅用于此目的,而不是作为一组规范化表的替代品,但这只是我的两个分.
我认为最好的解决方案是 #2。如果您使用像 mysql.
这样的事务数据库,甚至可以同时保存当前状态和相关事件我真的不喜欢并推荐解决方案 #1。
如果您对 #1 的关注是关于事件 versioning/upgrading;然后为每个新更改声明一个新的 class。不要太懒惰;或者沉迷于重用。让订阅者知道变化;给他们活动版本。
如果您对 #1 的担忧与 querying/interpreting 事件有关;然后您可以随时轻松地将事件推送到 nosqldb 或 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 { }
所以;使事件版本控制和升级明确;在域和代码库中。在部署新事件的来源之前,在订阅者中实施新事件的处理。和;如果不需要,不允许直接使用来自外部订阅者的域事件;放置一个集成层或类似的东西。
希望我的想法对你有用。
我读到了一种事件溯源方法,它包括:
- 有两个 table:聚合和事件;
根据您的用例:
一个。在聚合 table 上创建和注册,生成 ID、版本 = 0 和事件类型,并在事件 table;
上创建事件b。按 ID 或事件类型从聚合 table、事件中检索,应用业务案例,然后更新聚合 table(版本和事件类型),然后在事件 table.[=10 上创建事件=]
尽管我使用这种方法更新了聚合 table 上的某些字段,但它将事件 table 保留为仅附加并提高了性能,因为您拥有聚合的最新版本 table .
我会选择 #2,如果您真的想要一种通过事件类型进行搜索的有效方式,我会在该列上添加一个索引。
以下是访问本案所涉及主体数据的两种策略。 1) 当前状态和 2) 事件排序。 使用当前状态,我们处理事件但只保留主题的最后状态。 通过事件排序,我们保留事件并通过在每次需要状态时处理事件来重建当前状态。 事件排序更可靠,因为我们可以跟踪导致当前状态发生的所有事情,但它绝对效率不高。保留中间状态(快照)而不仅仅是最后一个状态是一种常识,以避免一直重新处理所有事件。现在我们拥有可靠性和性能。
在加密货币中有事件排序和本地快照——名称中的本地是因为区块链是分布式的,数据是复制的。