关于EventSourcing、微服务、CQRS的讲解

Explications about EventSourcing, Microservice, CQRS

我目前正在构建一个应用程序,我想使用微服务作为模式并使用 GraphQl 进行通信。我正在考虑使用 kafka / rabbitmq + authZ + auth0 + apollo + prisma。 运行 docker 上的所有这些。 我发现了很多关于事件溯源的资源,advantage/disavantage,我一直在研究它在现实世界中是如何工作的。到目前为止,我将这样做:

理想情况下:

现在如果我理解正确的话,使用 apache kafka + zookeeper :

如果我是对的,我可以假设:

我将尝试在概念层面上回答您的主要问题,而不会与框架和实现的细节联系在一起。希望这会有所帮助。

There would be 2 ways to validate if the request is valid:

. Write's side only get events (from event store, AKA zookeeper) to validate if the requested mutation is possible.

. Write's side get a snapshot from a traditional database to validate the requested mutation.

我会选择第一个选项。要执行命令,您应该依赖当前事件流作为确定模型当前状态的权威。

您的体系结构的读取模型只是最终一致的,这意味着在命令发生和它反映在读取模型上之间存在任意延迟。虽然你可以在你的架构上努力确保这个延迟尽可能小(即使你忽略这样做的成本)你总是会有一个 window 你的读取模型仍然不是最新的.

也就是说,您的命令应该 运行 与基于当前事件存储的命令模型相对应。

The main difference between event sourcing and basic messaging is the usage of the event-store instead of a entity's snapshot? In this case, can we assume that not all MS need an event's store tactic (i mean, validating via the event store and not via a "private" database)? If yes, does anyone can explain when you need event's store and when not?

事件溯源的整个概念是:不是将您的状态存储为仅反映此类数据最新阶段的“可更新”数据,而是将您的状态存储为一系列动作(事件),这些动作(事件)可以被解读为达到这样的境界。

因此,假设您的域中有一块内容(以自由形式表示法):

实体 A = { Id: 1;名称:“某事”; }

然后发生了一些事情,命令到达将此类实体的名称更改为“其他事物”。

在传统存储中,您将获取此类记录并将其更新为:

{ 编号:1;名称:“其他事物”; }

但是在事件源存储中,你不会有这样的记录,你会有一个事件流,其中包含如下数据:

{Id = 1 的实体创建} > {Id = 1 的实体重命名为“Something”} > {Id = 1 的实体重命名为“Other Thing”}

现在如果你按顺序“重放”这些事件,你将达到与传统存储相同的状态,只有你“知道”你是如何到达那个状态的,而传统存储会忘记这样的历史。

现在,回答您的问题,您完全正确。并非所有微服务都应该使用事件存储,甚至不推荐这样做。事实上,在微服务架构中,每个微服务都应该有自己的持久性机制(很多时候都是不同的技术)并且没有微服务可以直接访问另一个微服务的持久性(正如你的图表所暗示的“另一个 MS”到达“事件存储” “您的“比尔的 MS”)。

所以,你的基本决定因素应该是:

  • 您的微服务是否可以通过主动存储域内状态的演变(而不是被动地记录它)获得更多收益?

  • 您的微服务领域是您有兴趣分析旧计算的领域吗? (也就是说,能够将域恢复到给定的时间点,以便您可以了解其状态的演变模式 - 将此处视为您想要了解过去计算的复杂审计)

  • 即使您对这两个问题都回答“是”...这种架构增加的复杂性值得吗?

作为本主题的结束语,请注意您的模型中有多种模式交织在一起:

  • 事件溯源只是将状态存储为一系列操作而不是可更新的中央数据中心的行为。
  • 处理读取模型与命令模型的模式称为 CQRS(命令-查询责任分离)

这两种模式经常一起使用,因为它们非常匹配,但这不是先决条件。您可以将数据与事件一起存储,而不是使用 CQRS 将其拆分为两个模型,并且可以将域组织为两个模型(命令和查询),而无需将其中任何一个主要存储为事件。