Design patterns Microservice CQRS单独构建(写入)查询模型和读取模型

Design patterns Microservice CQRS单独构建(写入)查询模型和读取模型,design-patterns,microservices,scaling,cqrs,event-sourcing,Design Patterns,Microservices,Scaling,Cqrs,Event Sourcing,以下场景 每分钟从队列接收60000条消息。RESTAPI每分钟为来自这些消息的数据提供10次服务 我有一个带有事件源和CQR的微服务体系结构。因此,我的命令已经与查询部分分离。问题在于同步查询并查询它,而不是命令部分 每隔几分钟,使用事件源模式将大约60000条命令作为事件发送和存储。通过CQRS,实际数据(不是事件)被同步到另一个服务,该服务将数据存储在数据库中。同时,数据每隔几分钟只读取十几次 换句话说。这一个服务接收60000个写操作,但只有十几个读操作 我真的很想遵循微服务的设计模式,

以下场景

每分钟从队列接收60000条消息。RESTAPI每分钟为来自这些消息的数据提供10次服务

我有一个带有事件源和CQR的微服务体系结构。因此,我的命令已经与查询部分分离。问题在于同步查询并查询它,而不是命令部分

每隔几分钟,使用
事件源
模式将大约60000条命令作为事件发送和存储。通过CQRS,实际数据(不是事件)被同步到另一个服务,该服务将数据存储在数据库中。同时,数据每隔几分钟只读取十几次

换句话说。这一个服务接收60000个写操作,但只有十几个读操作

我真的很想遵循微服务的设计模式,也就是每个服务一个数据库,但是由于扩展的原因,我认为在我的场景中这是不可行的。写入数据库比读取数据库需要更大的扩展

我看到了一个解决方案,但答案建议使用CQR,我已经实现了。以前有人告诉我要删除事件源,但这仍然让我有60000次写入和10次读取


我的体系结构应该是什么来独立扩展读写?我正在考虑创建两个独立的服务,但这将违反每个服务一个数据库的模式。

要找到您问题的答案,您可能需要将微服务和CQR的思维过程结合起来

有两种观点可以帮助您思考这个问题:

  • 在CQR的众多优点中,其中一个好处是将数据的读取端和写入端分离开来,这正是针对您这样的需求,在您的需求中,性能需求存在许多数量级的差异。您需要能够以不同的方式扩展这两个部分,这就意味着在微服务世界中有两种不同的服务

  • 使用真正的CQR,您倾向于在数据的写入和读取部分之间没有关系/链接。一个完美的例子是使用RDBMS存储写端,并使用文档存储(比如MongoDB,甚至像ElasticSearch这样的索引)作为查询端,因为它支持聚合数据结构


  • 因此,IMHO,如果您希望能够单独扩展,并且不希望写入和读取之间存在任何争用,那么两个独立的服务是最好的选择。

    假设

    据我所知,问题在于您的写模型需要尽快反映读模型状态,因为您已经 每分钟仅读取10次,它们需要实时或接近实时地反映真实状态

    问题

    基于此假设,将此域拆分为2个微服务并使用CQR无法解决此问题。 为什么?

    因为如果你有一个写微服务和读微服务,并且你更新了读微服务 对于从Write micro service发布的事件,您将遇到延迟问题。 这意味着您将有大约50-100毫秒(大部分时间)的最小延迟 延迟会更大) 直到读微服务数据库与写微服务数据库同步。 这是正常的,在使用分布式系统时需要考虑到这一点 使用队列的系统

    基于此,将这部分域拆分为2个微服务并不是最好的方法(同样,这也是 基于我的假设,您需要几乎实时地读取微服务数据)

    可能的解决方案

    你能做什么? 在这里,您可以做几件事:

  • 选项-数据库复制和CQR

    • 数据库部分 同样,如果您需要最新的数据,您可以使用诸如写数据库的只读复制之类的方法。 SQLServer提供了类似于这种开箱即用的功能。我在我的一个项目中使用它。这意味着 您将拥有另一个数据库,SQL server将在其中将您的数据复制到数据库级别上的另一个数据库 (这将比整个过程快得多,发布到队列并使用来自另一个微服务的消息)。 此数据库将与您的写数据库完全相同,并且是只读的。这样,您的10次读取操作将 几乎总是最新的,延迟非常低。您可以在此处从SQL Server了解此功能

    • 后端的CQRS部分 当涉及到CQR时,您仍将继续使用它,并拥有2个微服务(写入和读取)。Write-micro服务将使用 主SQL Server实例和Read micro服务将使用主数据库的只读副本。牢记 此只读复制副本是一个单独的数据库,在单独的计算机上运行。因此,基于此,您将满足规则:“每个微服务一个数据库”。 当然,如果您使用的是Microsoft Sql Server,则此选项是可能的

  • 选项-使用事件源生成物化视图和服务器端CQR

    • 数据库部分 在这种方法中,您将使用物化视图,它将作为主或写微服务数据库在同一数据库上进行读取。例如,如果使用PostgreSQL,则可以使用Marten()进行事件来源和存储。它适用于.NET,但我想其他语言也有其他解决方案。Marten的优点是 您可以生成物化视图(称为投影视图),这些视图在聚合/模型更改时立即生成。 这意味着,例如,如果您使用事件源更改了某个客户对象,您将发布一个偶数