命令查询职责分离模式 CQRS Command Query Responsibility Segregation

CQRS

CQRS代表命令查询责任隔离。我最初听到的是格雷格·扬(Greg Young)描述的一种模式。其核心思想是,您可以使用与用于读取信息的模型不同的模型来更新信息。在某些情况下,这种分离可能很有价值,但请注意,对于大多数系统,CQRS会增加风险。

人们用于与信息系统进行交互的主流方法是将其视为CRUD数据存储。我的意思是,我们有一些记录结构,我们可以心智模式 ç reate新纪录,[R EAD记录,ü PDATE现有记录,并ð elete记录时,我们与他们所做的。在最简单的情况下,我们的交互都是关于存储和检索这些记录的。

随着我们的需求变得越来越复杂,我们逐渐摆脱了这种模式。我们可能希望以与记录存储不同的方式查看信息,也许将多个记录折叠成一个记录,或者通过组合不同位置的信息来形成虚拟记录。在更新方面,我们可能会发现验证规则,这些规则仅允许存储某些数据组合,甚至可能推断出与我们提供的数据不同的数据。
在这里插入图片描述
发生这种情况时,我们开始看到信息的多种表示形式。当用户与信息交互时,他们使用该信息的各种表示形式,每个表示形式都不同。开发人员通常会构建自己的概念模型,以用来操纵模型的核心元素。如果您使用的是领域模型,则通常是领域的概念表示。通常,您还应使持久性存储尽可能接近概念模型。

表示形式的多层结构可能会变得非常复杂,但是当人们这样做时,他们仍然将其解析为单个概念表示,该概念表示充当所有演示之间的概念整合点。

CQRS引入的更改是将概念模型拆分为单独的模型以进行更新和显示,分别按照CommandQuerySeparation的词汇分别称为Command和Query 。这样做的理由是,对于许多问题,尤其是在更复杂的领域中,具有相同的命令和查询概念模型会导致更复杂的模型,而这种模型不能很好地发挥作用。
在这里插入图片描述
通过单独的模型,我们最通常地表示不同的对象模型,它们可能在不同的逻辑过程中运行,也许在单独的硬件上。一个网络示例将使用户看到使用查询模型呈现的网页。如果他们发起更改,则将更改路由到单独的命令模型进行处理,结果更改将传达给查询模型以呈现更新的状态。

这里有很大的变化空间。内存中模型可以共享同一数据库,在这种情况下,数据库充当两个模型之间的通信。但是,他们也可以使用单独的数据库,从而有效地将查询方的数据库转换为实时ReportingDatabase。在这种情况下,两个模型或其数据库之间需要某种通信机制。

这两个模型可能不是单独的对象模型,可能是相同的对象在其命令端和查询端具有不同的接口,就像关系数据库中的视图一样。但是通常当我听说CQRS时,它们显然是分开的模型。

CQRS自然适合其他一些建筑模式。

  • 当我们远离通过CRUD与之交互的单个表示形式时,我们可以轻松地转到基于任务的UI。
  • CQRS非常适合基于事件的编程模型。经常看到CQRS系统被拆分成与Event Collaboration通信的单独服务。这使这些服务可以轻松利用事件来源。
  • 具有单独的模型会引发有关如何使这些模型保持一致性的问题,从而增加了使用最终一致性的可能性 。
  • 对于许多域,更新时需要很多逻辑,因此使用EagerReadDerivation简化查询侧模型可能很有意义 。
  • 如果写入模型为所有更新生成事件,则可以将读取模型构造为EventPosters,使它们成为MemoryImages,从而避免了许多数据库交互。
  • CQRS适用于复杂领域,该领域也可以从领域驱动设计中受益。

什么时候使用

像任何模式一样,CQRS在某些地方有用,但在其他地方则没有用。许多系统确实适合CRUD思维模型,因此应采用这种风格。对于所有相关人员来说,CQRS都是一次重大的精神飞跃,因此,除非收益值得实现,否则不应解决。尽管我成功地使用了CQRS,但到目前为止,我遇到的大多数情况都不是很好,因为CQRS被视为使软件系统陷入严重困境的重要力量。

特别是,CQRS应该仅用于系统的特定部分(DDD术语中的BoundedContext),而不应用于整个系统。用这种思维方式,每个有界上下文都需要自己决定如何建模。

到目前为止,我看到了两个方面的好处。首先,通过使用CQRS,一些复杂的域可能更容易解决。但是,我必须强调,这种对CQRS的适用性在少数情况下非常重要。通常,命令和查询端之间有足够的重叠,从而可以更轻松地共享模型。在不匹配的域上使用CQRS会增加复杂性,从而降低生产力并增加风险。

另一个主要优点是处理高性能应用程序。CQRS允许您将负载与读取和写入分开,从而可以分别扩展每个负载。如果您的应用程序发现读写之间存在很大差异,这将非常方便。即使没有这些,您也可以对双方应用不同的优化策略。例如,使用不同的数据库访问技术进行读取和更新。

如果您的域不适合CQRS,但是您的查询要求很高,则会增加复杂性或性能问题,请记住,您仍然可以使用ReportingDatabase。CQRS对所有查询使用单独的模型。使用报告数据库,您仍然可以将主系统用于大多数查询,但是将要求较高的查询卸载到报告数据库中。

尽管有这些好处,但您在使用CQRS时应非常谨慎。许多信息系统都非常适合以读取信息的方式更新的信息库概念,因此将CQRS添加到这样的系统可能会增加相当大的复杂性。我当然已经看到过这样的情况,它极大地拖累了生产力,甚至在一个有能力的团队的手中,也给项目增加了不必要的风险。因此,尽管CQRS是在工具箱中很好的一种模式,但是请注意,很难很好地使用它,如果处理不当,很容易砍掉重要的位。

原文

https://martinfowler.com/bliki/CQRS.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值