以正确的方式实施 CQRS / ES

Implementing CQRS / ES the proper way

最近我期待在我的微服务中实现带有事件源的 CQRS/ES 模式。

我一直在阅读这些模式,但我有一些问题无法在任何地方找到答案:

  1. 在做CQRS/ES的时候,每个微服务是不是应该有自己的local 不再有数据库(在微服务中)?

    我知道会有一个用于写入的事件存储和一个只读投影数据库,我完全理解它们的用途,但是微服务需要吗 他们自己的本地数据库出于什么原因? (优点/缺点)

    示例:订单微服务可以有本地订单数据库、项目服务和项目本地数据库等...除了事件源数据库和预测数据库实现.

  2. 如何验证之前微服务中是否存在某些数据 实际发出命令?

    假设我想下一个新订单,所以我假设我首先必须 检查该商品是否仍有库存,然后执行另一个 operation/s.

    但是,如果我想检查某件商品是否仍有库存,我应该在哪里 查询该数据,它是投影(只读)数据库,还是 每个微服务都有一个本地数据库?

此时我已经阅读了很多关于 CQRS / ES 的文章,但其中大多数只是解释概念,而不是真正深入到现实生活场景/解释如何实现它。如果您有任何建议,我将不胜感激。

非常感谢

一般来说,在处理微服务时,建议(无论您是否正在做 CQRS/ES)不要让两个微服务使用同一个数据库,或者至少不要让两个微服务使用同一个数据库写入同一个数据库。这允许每个微服务控制其架构,仅在微服务需要时才需要更改。这样做的另一个优点是数据库完全封装在服务中:它纯粹是一个实现细节。

实现读取模型的微服务完全有可能没有数据库:它可能能够将所有状态保存在内存中(一个例子可能是一个读取模型,它公开了监控基础设施的指标),或者它可能只是将事件从写入模型转换为命令到另一个服务(因此它的所有状态只是它在事件流中的位置)。

if i want to check if an item is still in stock, where do i query that data, will it be the projection (read-only) database, or a local database that each microservice has?

在事件源系统中,每个不是事件流的视图都是投影。因此,根据您的要求,您的服务可以根据事件查询其他服务或维护自己的视图。

请注意,在任何给定时刻,可能存在已发布到事件流的事件(即它已无可争议地发生),但也存在未处理该事件的投影:投影最终是与事件流一致。因此,检查一件商品是否有货只会告诉您该商品在过去的某个时间点有库存(没关系,用 Greg Young 的例子,没有库存数据可以保证没有任何东西被盗仓库,除非盗贼在带着战利品走出去时碰巧有礼貌地更新计数)。在您查询后的纳秒,它可能会收到一个事件的消息,这会导致您下订单之前缺货。

因此,如果商品没有库存,发送命令并让它拒绝您的订单可能是值得的。写端(这是系统中一致性更强的部分,尽管应该记住,在许多情况下,一个组件的事件是另一个组件的命令)没有义务接受每个命令;在这种情况下,“命令”实际上意味着“礼貌地请求将事件发布到符合我期望的宇宙状态的事件流”。