Gol*_*den 6 cqrs event-sourcing
在基于 CQRS / ES 的系统中,您将事件存储在事件存储中。这些事件涉及一个聚合,并且它们相对于它们所属的聚合有一个顺序。此外,聚合是一致性/事务边界,这意味着任何事务保证仅在每个聚合级别上给出。
\n\n现在,假设我有一个读取模型,它消耗来自多个聚合的事件(据我所知,这完全没问题)。为了能够以确定性的方式重播读取模型,事件需要某种全局排序,跨聚合 \xe2\x80\x93 否则您不知道是否在 B 的事件之前或之后重播聚合 A 的事件,或者如何混合它们。
\n\n实现此目的的最简单的解决方案是在事件上使用时间戳,但通常时间戳不够细(或者,换句话说,并非所有数据库都是相同的)。另一种选择是使用全局序列,但这在性能方面很差并且阻碍扩展。
\n\n你如何解决这个问题?或者我的基本假设是,读取模型的重播应该是确定性的,是错误的吗?
\n我看到这些选项:
全局序列
如果你的数据库允许,你可以使用timestamp+aggregateId+aggregateVersion作为索引。这通常在分布式数据库情况下效果不佳。
在分布式数据库中,您可以使用矢量时钟来获取全局序列,而无需锁定。
每个读取模型内的事件序列。您可以将所有事件存储在读取模型中,并在应用投影函数之前根据需要对它们进行排序。
允许非决定论并处理它。例如,在您的示例中,如果 add_user 事件到达时没有组 - 只需在读取模型中创建一个空组记录并添加用户。当 create_group 事件到达时 - 更新该组记录。毕竟,您已在 UI 和/或命令处理程序中检查到存在具有此aggregateId 的组,对吧?