代码之家  ›  专栏  ›  技术社区  ›  Markus S.

与事件源和cqr聚合

  •  1
  • Markus S.  · 技术社区  · 6 年前

    为了处理大量的遥测数据并仍然能够对数据执行快速查询,我使用azure函数和azure cosmos db采用事件源/cqrs模式。

    在我的体系结构中,入站遥测流存储在充当事件存储的cosmos db集合中。

    为了创建原始遥测数据的具体化视图,我使用另一个azure函数和cosmos db trigger,它对存储在我的事件存储中的所有新文档激活,并对这些文档执行转换。

    在每个文档的基础上处理文档是非常容易的。 最棘手的是,当我需要引用其他文档来计算我的物化视图时。

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

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

    使用这种方法的问题是,当我必须重新计算具体化视图时,因为在将来的版本中,我需要生成一些额外的视图。

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

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

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

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

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

    1 回复  |  直到 6 年前
        1
  •  1
  •   Markus S.    6 年前

    因此,总结一下@mikhail和@romaneremin的评论和我的想法,这将是处理这些场景的方法:

    重新计算视图时:

    • 删除现有聚合并从头开始重新生成 事件存储中的事件。

    如果事件总线传递“至少一次”(azure使用cosmosdb触发器的方式作为底层changefeedprocessor的结果):

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