【问题标题】:Aggregates with Event Sourcing and CQRS具有事件溯源和 CQRS 的聚合
【发布时间】:2018-06-20 17:36:47
【问题描述】:

为了处理大量遥测数据并仍然能够对数据执行快速查询,我采用了使用 Azure Functions 和 Azure Cosmos DB 的事件溯源/CQRS 模式。

在我的架构中,入站遥测流存储在 Cosmos DB 集合中,充当事件存储。

为了创建原始遥测数据的具体化视图,我使用了另一个带有 Cosmos DB 触发器的 Azure 函数,该函数在我的事件存储中存储的所有新文档上激活,对这些文档执行转换。

在每个文档的基础上处理文档非常容易。 棘手的地方在于,当我需要参考其他文档来计算我的物化视图时。

例如,当接收到的遥测事件包含相对计数器值(例如,特定操作中使用的能量)时。在我的物化视图中,我希望有一个包含所有能源消耗总和的文档。

现在一个简单的实现是在我的物化视图中查看该文档的当前状态,然后将该值增加新收到的值。

使用这种方法可能会遇到的问题是当我必须重新计算我的物化视图时,因为在未来的版本中我需要生成一些额外的视图。

对于重新计算,我只需在我的事件存储中触摸我想要重新计算的所有相关文档,触发再次计算物化视图的 Azure 函数。这会导致文档进入之前处理过的 Azure Function。

当发生重新计算时,如果我只是增加我的总和,我的计数器现在将不再准确,因为已经是总和一部分的文档将被再次添加。

解决这个重新计算场景的方法(我想到的)是:

  • 跟踪作为总和一部分的所有源文档并忽略 已经是总和一部分的文档的事件
  • 跟踪已经是总和一部分的最新遥测事件的序列号,并在重新计算时忽略序列号低于已经是总和一部分的事件。

您能给我一些关于如何正确解决这种情况的建议吗?

【问题讨论】:

  • 通常情况下,物化视图重新计算时,只是删除旧值,整个计算从头开始。在同一个计算中多次重播同一个事件对我来说听起来不合适。
  • 感谢您的评论,@Mikhail!在重播场景中,您的建议将是一个很好的解决方案,但我认为当我通过 changefeed 考虑消息的“至少一次”传递行为时,我需要一定程度的幂等性来计算这种物化视图.鉴于此,在正常执行期间,我可能会发生多次传递消息的情况。发生时,我的总和将不正确。您对这些情况有什么建议吗?
  • 您可以存储合理数量的上次应用事件的 ID - 以确保没有事件被应用两次。
  • 另外,如果您的写入端使用乐观锁定,您将在每个事件中拥有聚合 ID 和顺序版本。然后您可以跟踪您的聚合在读取模型中的版本。如果您错过了某个活动,或者发送了两次 - 您可以跟踪它。
  • @MarkusS,是的,如果您的事件总线提供“至少一次”。但我同意 Mikhail 的观点 - 如果您更改读取的模型代码,您应该从头开始重新构建它。

标签: azure-functions azure-cosmosdb cqrs event-sourcing materialized-views


【解决方案1】:

所以,总结 @Mikhail 和 @RomanEremin 的 cmets 以及我的想法,这将是处理这些场景的方法:

在重新计算视图的情况下:

  • 删除现有聚合并从头开始构建 事件存储中的事件。

如果事件总线提供“至少一次”(Azure 函数与 CosmosDb 触发器的行为方式是底层 ChangeFeedProcessor 的结果):

  • 版本 1:跟踪作为聚合文档中聚合的一部分的事件 ID(文档 ID),并忽略已经是聚合一部分的事件。
  • 版本 2:提供源事件的顺序版本(序列号)并将聚合所基于的版本存储在聚合文档中。计算聚合时,请根据事件的序列号检查此序列号。如果事件的序列号低于聚合文档:忽略,否则重新计算聚合并更新聚合所基于的序列号。

【讨论】:

    猜你喜欢
    • 2019-05-10
    • 2020-03-20
    • 2018-12-28
    • 2019-01-31
    • 2011-03-07
    • 2018-02-19
    • 1970-01-01
    • 2018-11-15
    • 2019-09-22
    相关资源
    最近更新 更多