CQRS,事件采购和扩展

Ond*_*cik 7 cqrs event-sourcing

很明显,基于这些模式的系统很容易扩展.但我想问你,究竟是怎么回事?关于可伸缩性我几乎没有问题:

  1. 如何扩展聚合?如果我要创建多个实例aggregate A,如何同步它们?如果其中一个实例处理该命令并创建一个事件,那么该事件应该传播到该agregate的每个实例?
  2. 不应该有一些业务逻辑存在要求的agregate实例吗?因此,如果我发出多个适用于aggregate A (ORDERS)并适用于某个特定订单的命令,则将它传递给同一个实例是有意义的.要么?

在本文中:https://initiate.andela.com/event-sourcing-and-cqrs-a-look-at-kafka-e0c1b90d17d8,他们正在使用Kafka进行分区.因此,用户管理服务 - 聚合被缩放,但仅订阅主题的特定分区,其包含特定用户的所有事件.

谢谢!

Rom*_*min 5

如何扩展聚合?

  • 仔细选择聚合,确保您的命令在许多聚合中合理地传播.您不希望拥有可能从并发用户接收大量命令的聚合.

  • 序列化发送到聚合实例的命令.这可以通过聚合存储库和命令总线/队列来完成.但对我来说,最简单的方法是使用Michiel Rook本文中描述的聚合版本控制进行乐观锁定

请求哪个agregate实例?

在我们的reSolve框架中,我们在每个命令上创建聚合实例,而不是在请求之间保留它.这种方法的速度非常快 - 获取100个事件并将它们缩减为聚合状态比在集群中找到正确的聚合实例更快.

这种方法是可扩展的,允许您无服务器 - 每个命令一个lambda调用,中间没有共享状态.聚合具有太多事件的极少数情况可通过快照解决.


Con*_*enu 5

如何扩展聚合?

聚合实例由它们的事件流表示。每个聚合实例都有自己的事件流。来自一个聚合实例的事件不会被其他聚合实例使用。例如,如果 ID=1 的订单聚合创建 ID=1001 的 OrderWasCreated 事件,则该事件永远不会用于补充其他订单聚合实例(ID=2,3,4...)。

话虽这么说,您可以通过根据聚合 ID 在事件存储上创建分片来水平扩展聚合。

如果我要创建聚合 A 的多个实例,如何同步它们?如果其中一个实例处理命令并创建一个事件,那么该事件是否应该传播到该聚合的每个实例?

你不知道。每个聚合实例与其他实例完全分离。

为了能够水平扩展命令的处理,建议每次从事件存储中加载聚合实例,通过重放其先前生成的所有事件。您可以执行一项优化来提高性能:聚合快照,但建议仅在确实需要时才执行此操作。这个答案可能会有所帮助。

难道不应该有一些业务逻辑来呈现要请求的聚合实例吗?因此,如果我发出适用于聚合 A(订单)并适用于一个特定订单的多个命令,则将其传递到同一实例是有意义的。或者?

您假设聚合实例在某些服务器的 RAM 上连续运行。您可以这样做,但这样的架构非常复杂。例如,当其中一台服务器出现故障并且必须由其他服务器替换时会发生什么?很难确定哪些实例存在并重新启动它们。相反,您可以拥有许多无状态服务器来处理任何聚合实例的命令。当命令到达时,您可以识别聚合 ID,通过重播之前的所有事件从事件存储中加载它,然后它就可以执行该命令。执行命令并将新事件保存到事件存储后,您可以丢弃聚合实例。到达同一聚合实例的下一个命令可以由任何其他无状态服务器处理。因此,可扩展性仅由事件存储本身的可扩展性决定。

  • @OndrejTomcik是的,聚合的ID例如是订单的ID (2认同)
  • @OndrejTomcik 聚合不能超出其边界,所以绝对不能 (2认同)