当前位置: 首页 > 知识库问答 >
问题:

CQRS、事件来源和Web应用程序

蓬高谊
2023-03-14

当我在读一些CQRS的资料时,有一个反复出现的问题我没有理解。例如,假设一个客户端发出一个命令。该命令由域集成,因此它可以刷新其域模型(DM)。另一方面,命令保存在事件存储中。这是最常见的情况。

1) 当我们说DM被刷新时,我假设数据被保存在底层数据库中(如果有的话)。我说得对吗?否则,我们将处理内存瞬态模型,我想这不是一件好事吗?(在客户端请求之外,状态不应该保留在服务器端的内存中)。

2)如果数据被持久化,我想依赖于它的读取模型会自动更新,因为每个请求它的客户端都会在应用程序中生成一个新的“状态/上下文”(在Web应用程序或RESTful架构的情况下)?

3) 如果命令被持久化,这是否意味着我们要处理事件来源(使用CQRS时通过构造)?事件寻源是否会使数据库更新过程无效?(就好像状态是从事件存储中重建的一样,维护数据库似乎毫无用处)?

CQRS是否只适用于多数据库系统(当数据在不同的数据库上传播时),如果它处理内存瞬态模型,它是否很适合Web应用程序或RESTful服务?

共有3个答案

仲孙阳
2023-03-14

数据的持久性并不是严格需要的。在足够多的不同位置(千兆空间)有足够多的副本就足够了。所以不,不需要数据库。这是荷兰eBay等价物在生产中使用的(至少几年前是这样)。

邓阳炎
2023-03-14

要解决的问题是,唯一存储的是事件*。从事件重新生成域模型。

所以是的,正如您所说,域模型是内存瞬态的,因为不存储域模型的表示*,只存储发生在域中以使模型处于当前状态的事件。

加载域模型中的元素时,会创建元素的新实例,然后以正确的顺序一个接一个地重放影响该实例的事件,以将元素置于正确的状态。

您可以保留域对象的实例并订阅新事件,以便它们可以保持最新,而无需每次都从所有事件中加载它们,但通常它的速度足以从数据库中加载所有事件并每次都应用它们,就像您可以在每次调用Web服务时从数据库中加载实例一样。

*除非您有域对象的快照以减少您需要加载/处理的事件数量

邹博裕
2023-03-14

1)如前所述,真正存储的只有事件。命令所做的唯一事情是在事件引发之前进行一致性检查。在伪代码中:

public void BorrowBook(BorrowableBook dto){
    if (dto is valid)
        RaiseEvent(new BookBorrowedEvent(dto))
    else
        throw exception
}

public void Apply(BookBorrowedEvent evt) {
    this.aProperty = evt.aProperty;
    ...
}

当前状态通过顺序“应用”检索。因此,您必须在设计阶段特别注意,因为有一些常见的陷阱需要避免(也许您已经阅读过了,但让我推荐一下Martin Fowler的这篇文章)。

到目前为止还不错,但这只是事件源。如果您决定使用不同的数据库来持久化聚合的状态,CQRS就会发挥作用。在我的项目中,我们有一个投影,每隔x分钟将新事件(来自事件存储)应用到聚合上,并将结果保存在单独的MongoDB实例上(表示层将访问此DB以进行读取)。这种模型显然最终是一致的,但通过这种方式,您可以真正将命令(写入)和查询(读取)分开。

2) 如果您决定将写入模型与读取模型分开,则可以使用各种选项来使它们同步:

  • 每隔x秒应用最后一个检查点的事件(一些解决方案提供快照以避免重新应用繁重的命令)
  • 订阅事件并在事件引发时更新读取模型的投影

3)唯一存储的是事件。事实上,我们有一个事件存储,而不是命令存储:)

数据库没用吗?看情况!你需要重新申请多少个事件才能将聚合到当前状态?三个?也许你不需要有读取模型的数据库。

 类似资料:
  • 很明显,基于这些模式的系统是易于扩展的。但我想问你,具体怎么做?关于可伸缩性,我没有什么问题: 如何缩放聚合体?如果我将创建

  • 我想创建一个CQRS和事件源架构,非常便宜,非常灵活,非常简单。 我想确保事件永远不会失败,至少到达发布者/事件存储,永远,因为这是业务所在。 天蓝 有了azure,我似乎不知道该用什么。 Azure服务总线 蔚蓝函数 Azure webjob(我想这可以用Azure函数代替) ??(还有什么我忘了或者不知道的?) null 你的经验说明了什么? 其他替代方案呢?(例如:)?

  • 我开始阅读与CQRS相结合的事件源模式。据我所知,CQRS模式是一种将写操作和读操作分开的模式。事件源是一种模式,系统中的一切都由触发事件的命令启动。事件源模式需要一个事件总线。有几件事我没弄明白。 事件存储区包含发生在某个实体上的所有事件。如果我想查询这个实体的当前状态,我需要查询发生在这个实体上的所有事件,并重新创建它的当前状态。 所有事件历史记录都在事件存储区中。 为什么我不能有一个负责将每

  • 我在CQRS/ES设计中有一个计时案例。为了便于讨论,让我们以Microsoft关于这个主题的示例会议管理为基础(https://msdn.microsoft.com/en-us/library/jj554200.aspx)。 假设在第1分钟创建会议(最大座位数为20)。 在第4分钟,事件到达order mgmt上下文,因此创建了一个座位可用性。 在第7分钟,用户下了一个订单(通过订单管理),购买

  • 事件源和CQRS很棒,因为它让rids开发人员被一个预先建模的数据库所困,除非有一个大的数据迁移项目,否则开发人员必须在应用程序的生命周期内使用该数据库。CQRS和ES还有其他好处,比如扩展eventstore、审计日志等,这些都已经遍布互联网。 但是缺点是什么呢? null

  • 这个问题与Axon Server/Framework的关系非常松散,因为我是在学习和尝试学习如何构建微服务时专门学习它的。由于在没有实际经验的情况下很难了解所有的架构模式(而且在没有一个大型应用程序来实际测试/构建的情况下,很难从实际经验开始),所以我在这里提出了很多理论(我的问题可能很愚蠢,对不起,我还在学习中)。 我下载了Axon Server,并成功地在三个独立的微服务中构建和运行了包含的g