CQRS 是一种 微服务 架构模式 ,它代表命令和查询责任分离。
这种模式背后的基本思想是将写操作与读操作分开。不是使用一个数据存储来执行 CRUD 操作,而是在一个数据存储上执行读取操作,并在不同的数据存储上执行创建/更新。
CQRS 承诺对大规模应用程序的稳定性和可 扩展性 以及显着的性能改进。
CQRS 模式由 Bertrand Meyer 设计,作为开发 Eiffel 编程语言的一部分。Greg Young 创造了“CQRS”一词。
CQRS 在哪里使用?
CQRS 通常在准备就绪的大规模分布式应用程序中是首选。也就是说,如果应用程序中的读取次数远远超过写入操作的次数。
此模式的另一个合适用例是读取操作繁重且数据存储副本可以放置在应用程序接收高流量的地理位置附近,从而提高数据库读取操作的性能。
CQRS 是如何实现的?
到目前为止,我们知道要实现 CQRS ,我们将使用两个数据存储库。
通常,写入操作首选关系数据库,其中可以应用所有数据约束,并使用NoSQL 数据库支持读取操作。这意味着,两种不同的数据模型用于写入和读取操作。
自然,人们会想到的问题是这两个存储库中的数据如何同步?
这就是事件驱动 架构 出现的地方。
考虑一个用户调用POST API的场景,执行一些验证,然后将数据及其约束更新到我们的关系数据库中。
将数据插入数据库后,将调用触发器,该触发器将更新所有事件处理程序(事件驱动架构)以更新读取的数据库。
当另一个用户调用 GET API 时,应用程序将从NoSQL 数据库中检索相关数据并将其发送回用户。用于实现 CQRS 的最流行的基于 JAVA 的框架是 Axon。
Axon 使用命令和处理程序来调用和处理相应的事件。 你可以在Github 上找到完整的代码。
使用 CQRS 有什么好处?
使用 CQRS 的主要好处包括:
灵活的扩展——读写数据存储可以根据需求独立扩展。 简单查询——由于读取和写入的数据模型是分开的,读取数据模型可以设计成避免复杂查询的方式。 提高性能——通过优化读取操作并将数据存储副本放置在不同的地理位置,读取繁重的操作可以显着提高性能。使用 CQRS 的缺点是什么?
复杂性——事件驱动的系统构建和维护起来很复杂。尽管有像 Axon 这样的框架可以处理数据库写入、发布事件和通知各种处理程序,但也有读写模型不同步的情况。 一致性——CQRS 和事件驱动架构旨在确保数据在所有涉及的系统中保持一致,但在消息失败的情况下,读取数据库将不同步。结论
在读取次数远大于写入次数的情况下,CQRS 是一种需要考虑的模式。特别是在读取操作要高度优化并且不需要执行任何业务逻辑或验证的情况下。读取操作就像获取数据、加载 DTO 并将其传递给客户端一样简单。
实现这样一个系统的最大挑战是确保避免数据重复,读取数据库永远不会过时,并且写入数据库的所有条目最终也会在读取数据库中一致地更新。
尽管从概念上讲,这听起来很简单,但 CQRS 并不那么容易实现和调试。