如何在CQRS /事件源中以确定的方式重放? [英] How to replay in a deterministic way in CQRS / event-sourcing?

查看:86
本文介绍了如何在CQRS /事件源中以确定的方式重放?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在基于CQRS / ES的系统中,您将事件存储在事件存储中。这些事件是指一个聚合,并且它们相对于它们所属的聚合具有顺序。此外,聚合是一致性/事务边界,这意味着任何交易担保都仅在每个聚合级别上给出。

In CQRS / ES based systems, you store events in an event-store. These events refer to an aggregate, and they have an order with respect to the aggregate they belong to. Furthermore, aggregates are consistency / transactional boundaries, which means that any transactional guarantees are only given on a per-aggregate level.

现在,假设我有一个读取模型会消耗多个中的事件聚合(非常好,AFAIK)。为了能够以确定性的方式重放读取的模型,事件需要某种跨聚集的全局排序–否则,您将不知道是否在聚集A的事件之前或之后重放聚集A的事件,或者不知道如何混合

Now, supposed I have a read model which consumes events from multiple aggregates (which is perfectly fine, AFAIK). To be able to replay the read model in a deterministic way, the events need some kind of global ordering, across aggregates – otherwise you wouldn't know whether to replay events for aggregate A before or after the ones for B, or how to intermix them.

最简单的解决方案是在事件上使用时间戳,但通常时间戳不够细(或者换句话说,并非所有数据库都是相同的)。另一个选择是使用全局序列,但这在性能上是不利的,并且会妨碍扩展。

The simplest solution to achieve this is by using a timestamp on the events, but typically timestamps are not fine-granular enough (or, to put it another way, not all databases are created equal). Another option is to use a global sequence, but this is bad performance-wise and hinders scaling.

您如何解决此问题?还是我的基本假设,即读取模型的重放应该是确定性的,错误的?

How do you solve this issue? Or is my basic assumption, that replays of read models should be deterministic, wrong?

推荐答案

我看到以下选项:


  • 全局序列

  • Global sequence


  • 如果您的数据库允许它,则可以使用timestamp + aggregateId + aggregateVersion作为索引。在分布式数据库的情况下,这通常无法正常工作。

  • if your database allows it, you can use timestamp+aggregateId+aggregateVersion as an index. This usually doesnt work well in the distributed database case.

在分布式数据库中,您可以使用向量时钟以获取没有锁定的全局序列。

in the distributed database you can use vector clock to get a global sequence without having a lock.

每个读取模型中的事件序列。您可以将所有事件直接存储在读取的模型中,并在应用投影函数之前根据需要对它们进行排序。

Event sequence inside each read model. You can literally store all events in the read model and sort them as you want before applying a projection function.

允许不确定性并加以处理。例如,在您的示例中,如果add_user事件到达时没有组-只需为读取的模型创建一个空的组记录并添加一个用户即可。并且当create_group事件到达时-更新该组记录。
毕竟,您已经在UI和/或命令处理程序中签入了
是具有此gregationId的组,对吗?

Allow non-determinism and deal with it. For instance, in your example, if there is no group when add_user event arrives - just create an empty group record to the read model and add a user. And when create_group event arrives - update that group record. After all, you have checked in UI and/or command handler that there is a group with this aggregateId, right?

这篇关于如何在CQRS /事件源中以确定的方式重放?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆