首页 > 解决方案 > 使用 EventSourcing 和大量事件进行聚合设计

问题描述

我想从 EventSourcing 开始冒险。作为一个游乐场,我有一个系统可以从阵列中组织的一组传感器中收集数据。每个传感器都有一个值,例如温度。我需要从这个系统中得到的是

  1. 获取传感器读数的当前值
  2. 上个月的传感器值历史记录
  3. 当传感器值发生变化时,我必须计算数组“状态”并存储它(也是一个月)
  4. 数组“状态”可以由用户手动更正

阵列和传感器的数量正在增长。对于每个阵列,我每秒有很多读数。

现在我想将阵列作为与传感器的聚合作为它的实体。在这种情况下,每个 Sensor 读数更新都会升级 Array Aggregate 版本。这会在一个月内产生 > 10M 的更改。在这个设计中,我不能切断不旧的事件。我想不出一年数据后恢复 ReadModels 所需的时间。

我想我可以将当​​前状态存储为 CRUD 表并从阵列中删除传感器当前数据。保持定义。然后我可以使用将处理传感器数据流的服务,检查阵列“状态”并将阵列“状态”保持为单独的聚合。服务将发出“传感器数据更新”事件。此事件将触发 ReadModel 保持历史数据处理 1 个月的约束。我不会用传感器读数事件污染事件存储。如果是数组“状态”,我将能够从事件存储中删除整个过去的“状态”聚合。数组将只保留 Sensor 定义,因此 EventStore 会相对较小。

我失去了完整的历史。我无法恢复我 1 个月的信号历史记录 ReadModel。我必须额外注意不要破坏它。

目标是学习如何扩展 EventSourcing / CQRS 系统。如何在几小时而不是几天内处理大型 EventStore 并重建损坏或扩充新的 ReadModel。

这个想法适合 ES / CQRS 吗?(编辑:可以使用不是来自聚合的事件流来更新 RM 吗?)

如何处理不断增长的事件存储和修复损坏的 ReadModels 的问题?

谢谢!

标签: cqrsevent-sourcing

解决方案


聚集了很多事件

聚合是写端的一个术语(CQRS 中的 C)。聚合接收命令,并使用其状态将事件发送到事件存储中。聚合状态是使用事件存储中的事件构建的。因此,如果给定聚合有很多事件,则构建状态需要时间。

为了加快为聚合构建状态,CQRS/ES 框架正在使用快照 - 这是为特定聚合版本存储的序列化聚合状态,因此您不是从一开始就构建状态,而是从最新快照。例如,您可以存储每 100 个事件的快照。如果您的投影功能发生变化,请不要忘记重建它们。reSolve等框架正在透明地为您执行此操作。

你的场景

在您的特定情况下,在我看来,您的业务逻辑是微不足道的,这意味着您不需要聚合状态来计算任何东西或做出决定 - 没有业务逻辑,您基本上只是存储由传感器生成的事件. 因此,在您的自定义框架中,您可以避免在写入端构建聚合状态 - 只需将事件存储为传感器数据传入。

在读取端,您将照常使用事件流 - 在接收到事件后,您可以将其存储到具有必要分类或时隙的读取模型数据库中。

如果您不需要 ReadModel 中的旧数据 - 您可以在重建期间跳过旧事件 - 它应该非常快。

如果您不想在事件存储中存储旧事件 - 您可以删除它们,但这不再是真正的事件源。


推荐阅读