微服务——事件存储技术(在事件溯源解决方案中)是否在所有微服务之间共享?

Microservices - Is event store technology (in event sourcing solutions) shared between all microservices?

据我目前的一点点经验,我可以理解,关于"microservice"的核心概念之一是它依赖于独立于其他微服务的自己的数据库。

深入研究如何在微服务系统中处理分布式事务,最好的策略似乎是事件溯源模式,其核心是事件存储。

不同微服务之间是否共享事件存储?或者每个微服务有多个独立的事件存储数据库和一个公共事件代理?

如果第一个选项是解决方案,使用 CQRS 我现在可以假设每个微服务的数据库都用作查询端,而共享事件存储位于命令端。这是一个错误的假设吗?

既然我们进入了主题:在使用乐观锁定在流中并发写入的情况下,我必须重试多少次?

非常感谢您给我的每条建议!

通常:在包括微服务在内的服务架构中,每个服务都在私有数据库中跟踪其状态。

"Private" 这里主要表示不允许其他服务写入或读取它。这可能意味着每个服务都有自己的专用数据库服务器,或者服务可能共享一个设备但只对自己的部分具有访问权限。

换句话说:服务通过 public api 共享信息相互通信, 而不是 通过将消息写入彼此的数据库。

对于使用事件源的服务,每个服务只能对其流进行读写访问。如果这些流恰好存储在同一个家中 - 很好;但系统的正确性不应该依赖于将它们的事件存储在同一设备上的不同服务。

Is the event store shared between different microservices? Or there are multiple independent event stores databases for each microservice and a single common event broker?

从他们的角度来看,每个微服务都应该写入自己的事件存储。这可能意味着同一实例内的不同实例或不同分区。这允许独立扩展微服务。

If the first option is the solution, using CQRS I can now assume that every microservice's database is intended as query-side, while the shared event store is on the command-side. Is it a wrong assumption?

有点。正如我在上面所写,每个微服务都应该有自己的事件存储(或共享实例中的分区)。微服务不应将事件附加到其他微服务事件存储。

关于读书活动,我觉得一般来说读书活动应该是允许的。轮询事件存储是将更改传播到其他微服务的最简单(也是我认为最好的)解决方案。它的优势在于,远程微服务会以它可以的速率和它想要的事件进行轮询。这可以根据需要通过创建事件存储副本来很好地扩展。

在某些情况下,您不希望发布 事件存储中的每个领域事件。有人说可能存在其他微服务不应依赖的内部域事件。在这种情况下,您可以将事件标记为免费(或不免费)供外部消费。

在微服务中传播更改的最干净的解决方案是让其他微服务可以订阅的实时查询。它的优点是投影逻辑不会泄漏到其他微服务,但也有缺点,即发出微服务必须定义+实现这些查询;当您注意到其他微服务复制投影逻辑时,您可以这样做。此查询的一个示例是电子商务应用程序中的总订单价格。每次在订单中添加 to/removed from/updated 项目时,您可能会发布这样的查询 WhatIsTheTotalPriceOfTheOrder

And since we are in the topic: how many retries I have to do in case of a concurrent write in a Stream using optimistic locking?

想写多少就写多少,直到写入成功。你可以有一个 99999 的限制,只是为了在重试机制出现严重错误时检测到。在任何情况下,只有在同一时间在同一流(对于一个聚合实例)而不是对整个事件存储完成写入时,才应重试并发写入。

TLDR:所有这些模式都适用于单个有界上下文(服务,如果你愿意),不要在你的有界上下文之外分发域事件,将集成事件发布到 ESB(企业服务总线)或类似的东西上,作为 public 界面。

好的,我们这里有三种模式,先分别简要介绍一下,然后再一起介绍。

  1. 微服务
  2. CQRS
  3. 事件溯源

微服务

https://docs.microsoft.com/en-us/azure/architecture/microservices/ 核心 objective:将系统中的更改隔离并解耦到各个服务,从而实现独立部署和测试而不会产生附带影响。 这是通过将更改封装在 public API 后面并限制服务之间的运行时依赖性来实现的。

CQRS

https://docs.microsoft.com/en-us/azure/architecture/patterns/cqrs 核心 objective:在单个服务中将写关注点与读关注点隔离和解耦。 这可以通过几种方式实现,但核心思想是读取模型是针对查询优化的写入模型的投影。

事件溯源

https://docs.microsoft.com/en-us/azure/architecture/patterns/event-sourcing 核心 objective:使用业务领域规则作为您的数据模型。 这是通过将状态建模为不可变域事件的仅附加流并通过从头重放流来重​​建当前聚合状态来实现的。

一起

这里有很多很棒的内容https://docs.microsoft.com/en-us/previous-versions/msp-n-p/jj554200(v=pandp.10) 其中每一个都有其自身的复杂性、权衡和挑战,虽然这是一个有趣的练习,但您应该考虑成本是否超过收益。所有这些都适用于单个服务或限界上下文。一旦开始在服务之间共享数据存储,就会面临问题,因为共享数据存储不能单独更改,因为它现在是一个 public 接口。

而是尝试将 integration events 发布到共享总线,作为其他服务和限界上下文的 public 接口,以使用和使用构建其他域上下文数据的投影。

将集成事件发布为当前聚合状态的幂等快照(更新 X,删除 X)是个好主意,尤其是当您的总线不是持久的时。这允许您在需要时从域重新发布集成事件,而不会在消费者之间产生不一致的状态。