vlambda博客
学习文章列表

.NET CQRS-一种读写分离的数据处理模式

译者按:
本文是翻译自Martin Fowler的一篇博客。

老马同志向来是我所敬仰的大师级人物,现在的“微服务”这个词就是从老马同志的博客开始火起来的。

原文链接

CQRS

Martin Fowler 14 July 2011

CQRS指的是命令查询职责分离模式,最早我听 Greg Young 提起过,该模式的核心思想是把数据的读操作和写操作分离开来。在某些场景下这种模式很有用,但 CQRS 也会增加系统的复杂性。

大多数情况下人们把信息系统作为可以进行增、删、改、查的数据存储库。我们可以在记录结构的 mental model 上进行创建、查看、更新和删除。所有这些活动可以被概括成两类:存储和检索。

当需求变复杂时,CRUD 模式就显示出了不足。我们可能想用特殊的方式查看记录:比如说把多条记录合并为一条;或把不同地方的记录整合为一条虚拟记录。而实际操作时限制重重,通常情况下我们只能进行特定数据的合并,甚至有时存储起来的信息跟我们提供的根本不一致。

我们会接触到很多信息形式。当用户进行操作时所面对的信息的变现形式是不一样的,而这些不同的形式代表的是同样的信息。开发人员通常使用操作模型的核心元素来构建概念模型。如果一个人在使用 Domain Model,那 Domain Model 就是他心目中 domain 的概念展示,同时,他也会尽可能的让持久性存储更接近整个概念模型。

这种多层表现形式的结构十分复杂,但对单个个体来说,他使用的是单一的概念模型,但这个概念模型其实代表了所有变现形式的整合。

CQRS 把传统概念模型中的更新和查看区分开来,就是我们熟知的 Command(命令)和 Query(查询)。在很多情境下,尤其是领域模型比较复杂时,命令和查询使用同一个模型很容易出现问题。

模型分离意味着不同的对象模型、不同的逻辑流程甚至是独立的硬件。web 应用使用查询模型来显示正在进行访问的用户。如果用户发出命令,命令会被传输到独立的命令模型进行处理,然后由独立的查询模型来展示最新状态。

这样操作空间就很大了。当这两个模型把一个数据库作为通信桥梁时,内存模型也可以共享这个数据库。当然,它们也可能使用单独的数据库,查询端就可以使用实时的 ReportingDatabase(报告数据库)。在这种情况下,这两个模型或它们的数据库之间需要建立通信机制。

这两个模型可能会共用对象模型,然后对象模型对命令端和查询端提供不同的接口,就像关系数据库视图一样。但通常情况下的 CQRS,都是使用独立模型。

CQRS 对其他一些体系结构模式也适用。
• 我们可以很容易地从基于 CRUD 模式的用户交互向基于任务的用户交互转变。
• CQRS 非常适合基于事件的编程模型。CQRS 系统中分离的服务与 Event Collaboration(事件协作)进行通信是很常见的。这些服务可以轻松使用 Event Sourcing。
• 模型分离对保持模型一致性的难度提出了质疑,进而提高了使用 eventual consistency(最终一致性)的可能性。
• 对很多域来说,大部分逻辑只有在更新数据时才会被调用,因此使用 EagerReadDerivation 简化查询端模型很有必要。
• 如果写模型针对所有更新都会生成事件,读模型可以采用 EventPosters 结构,把事件按 MemoryImages 的形式进行存储从而避免大量数据库交互。
• CQRS也适用于复杂领域,Domain-Driven Design 可以提供更多帮助。


什么时候可以考虑 CQRS

CQRS并不适用于所有场景,只适用于某些特定的场景。大部分系统都使用传统的 CRUD 模式,人们对它的认知度也更高。CQRS 模式对人们来说跨度太大,所以说除非它成效显著,不然很少有人愿意去尝试。虽然我见过 CQRS 的成功案例,但目前为止,CQRS 大多数情况下的运行不尽人意,人们认为使用 CQRS 会让软件系统出现问题。

CQRS 可以被应用到某些系统的特定部分(就像 DDD 中的 BoundedContext),而不应该被应用到整个系统。每个 Bounded Context 都需要决定如何建模。

目前来说,CQRS 在两个方面的应用很好。首先,CQRS 可以轻松处理复杂场景。然而我想强调一下,这种情况是非常少的。通常情况下,命令和查询重叠较多,共用一个模型更简单些。如果 CQRS 和场景不匹配就会增加系统的复杂性,因此降低生产效率、增加风险。

CQRS 在高性能应用方面用处很大。CQRS 对读取和写入分开考虑。如果应用程序读取和写入比例差距较大,采用 CQRS 就很合适。即使不采用这种模式,你也要为读取和写入采取不同的优化策略。举个例子:使用不同的数据库访问技术进行读取和更新。

如果你的场景不适合使用 CQRS,但你又面临查询所带来的复杂性或性能问题,可以尝试一下 ReportingDatabase。CQRS 中所有查询都使用单独的模型,采用 reporting database 后,大部分查询仍使用原系统,而那些特殊要求的查询则由 reporting database 处理。

尽管好处众多,但在使用 CQRS 时仍需谨慎。大多数信息系统的读写方式是相同的,应用 CQRS 会增加系统的复杂性。我也见过某些案例,在应用 CQRS 后反而降低了生产效率、增加了项目不必要的风险。因此,CQRS 虽然是很好的工具,但也要小心使用,否则会适得其反。

出处:https://blog.csdn.net/frank_zhu_bj/article/details/53222078