【问题标题】:event sourcing relationships and basics事件溯源关系和基础知识
【发布时间】:2019-03-19 09:31:00
【问题描述】:

我在一家初创公司工作,我们希望通过事件溯源构建一个基本的概念证明。任何人都可以对这些基本问题提供一些澄清吗?

  1. 事件源是事件流的集合吗?
  2. 您是否有每个有界上下文的事件源?或者可能是每个 DDD 聚合(例如汽车及其更改)?
  3. 是否每个事件源都有自己的数据存储?
  4. 以汽车的事件源为例,其中每个事件流都基于唯一的 carId?

关于可能的基本流程的问题...这听起来完整且有意义吗?

客户端 --> eventStore API --> 存储事件 --> 可能将消息发布到队列 --> 向客户表示赞许 --> 去构建您的读取模型/索引? --> 客户端公开发布事件 --> 同一事件的其他消费者现在可以根据该事件采取行动。

我对“构建读取模型”部分并不完全清楚......我想您可以在任何单独的数据存储中构建“投影”?或者只是索引实际事件存储中的数据以进行快速查询?

对这些问题的任何澄清都会很棒。

谢谢! -罗恩

【问题讨论】:

    标签: domain-driven-design cqrs event-sourcing


    【解决方案1】:

    我将为您提供一些我使用过/见过使用过的基本事件溯源术语。另外,我将在 CQRS 的上下文中使用事件溯源,尽管它可以单独使用(我直到现在才这样做)。

    事件存储是事件的持久性(数据库)。应用程序的写/命令和读/查询端对事件存储有不同的要求。

    写入端需要聚合发出的事件必须按顺序并防止并发插入。人们将此称为 事件流 = 聚合实例(即 Product#1234)发出的所有事件。 Event 流在读取的时候也应该很快,也就是说,从 Event 流中按照发出的顺序读取所有的事件,最早的在前,应该很快;这是在执行每个命令之前进行聚合补水所必需的。

    读取方希望所有事件按顺序排列,跨越所有聚合。如果您负担得起这个要求,那么 Readmodel 的构建会更简单。但是,通过更大的开发和设计工作,可以创建不需要全序的读取模型。

    大型系统的问题在于,一般来说,Readmodels 需要来自多个事件存储的事件

    事件源是事件流的集合吗?

    如果“事件源”是指“事件存储”,那么是。

    每个有界上下文都有一个事件源吗?或者可能是每个 DDD 聚合(例如汽车及其更改)?

    最简单的系统是具有单个事件存储实例的系统。这是因为 Readmodels 只需要连接到一个实例,并且您可以拥有事件的总顺序。

    如果系统太大,则不可能拥有单个事件存储。这意味着您不能拥有事件的总顺序,这意味着读取模型更难构建(并非不可能)并且运营成本会增加。

    因此,您必须做出权衡。一个不错的权衡是每个有界上下文都有一个事件存储。

    每个事件源都有自己的数据存储吗?

    这个问题在这个答案的上下文中没有意义。一个事件存储 = 一个数据存储。

    以汽车的事件源为例,其中每个事件流都基于唯一的 carId?

    是的,每个汽车实例(具有唯一 ID)都有一个事件流。

    客户端 --> eventStore API --> 存储事件 --> 可能将消息发布到队列 --> 向客户表示赞许 --> 去构建您的读取模型/索引? --> 客户端公开发布事件 --> 同一事件的其他消费者现在可以根据该事件采取行动。

    这取决于您的架构/风格/Readmodels 如何接收事件。

    您可能有一个简单的同步系统,当在同一个进程/线程中处理命令,发出事件时,它们会立即持久化到事件存储中,然后所有的 Readmodel 和 Sagas 都会收到这些新事件,全部同步完成,一个接一个。

    一个更复杂的系统执行命令,将事件持久化到事件存储,然后将响应返回给客户端。在一个单独的过程中,Readmodels 和 Sagas 轮询来自 Event store(提供此类 API)的新事件并在后台处理它们。

    其他解决方案使用消息队列;这有点难以做到,因为不能以一种安全且可扩展的方式将事件持久保存到事件存储,并以原子方式将它们发布到消息队列(无论是成功还是无)。

    【讨论】:

    • 谢谢!我正在努力解决的一件事是如何“重播”事件以获取状态。每个人都在谈论这个,就像您可以轻松地查询您的读取模型并获取状态一样。但是,您不必通过一系列函数来运行这些事件吗?这不需要一堆编码才能“重放”它们吗?
    • 例如,在银行系统中。这些事件可能是“Deposited5Dollars”,然后是“Withdrew4Dollars”......您不能只查询这些事件以获得最终余额,对吗?您必须通过一系列函数运行这些事件才能得出最终平衡,不是吗?如果是这样,我正在为那会是什么样子而苦苦挣扎
    • @RonStevenson 是的,当然。有 3 种类型的组件派生事件:聚合、Readmodel 和 Sagas。在 OOP 世界中,每一个都可以作为一个类来实现。一个类有方法。在 CQRS 中,您可以使用 handleXXX 形式的方法,其中 XXX 是事件类型。如何调用这些方法很大程度上取决于框架。
    • @RonStevenson 这是一个读取模型:github.com/xprt64/todosample-cqrs-es/blob/master/src/Domain/…
    • 太棒了,谢谢!感谢所有的答案和帮助:)
    猜你喜欢
    • 2015-10-07
    • 2016-09-21
    • 1970-01-01
    • 2012-05-12
    • 1970-01-01
    • 2010-09-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多