【发布时间】: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