什么是CQRS?
CQRS(Command and Query Responsibility Segregation),命令查询责任分离。一种将数据存储的读取和更新操作分开的模式。从名称简单理解则是将commad与query分离的一种模式。
CQRS 将系统中的操作分为两类:
- Command:命令则是对会引起数据发生变化操作的总称,即我们常说的新增,更新,删除这些操作都是命令
- Query:查询则是不会对数据产生变化的操作,即我们常说的查找数据。
CQRS 的核心思想是将这两类不同的操作进行分离,然后在两个独立的「服务」中实现。这里的「服务」一般是指两个独立部署的应用。在某些特殊情况下,也可以部署在同一个应用内的不同接口上。这两个服务对应的数据源也应该是相互独立的,即更新操作在一个数据源,而查询操作在另一个数据源上。
CQRS架构
我们先来看一下CQRS架构图:
从图上可以看到,当 command 系统完成数据更新的操作后,会通过「领域事件」的方式通知 query 系统。query 系统在接受到事件之后更新自己的数据源。所有的查询操作都通过 query 系统暴露的接口完成。
CQRS的优点
- 独立缩放。CQRS允许读取和写入工作负载独立扩展,并可能导致更少的锁争用。
- 优化的数据模式。读取端和写入端可以分别使用针对自身的不同的优化模式,例如读取段使用针对查询优化的模式,而写入端使用针对更新优化的模式。
- 安全。更容易确保只有正确的域实体对数据执行写入操作。
- 关注点分离。分离读写端可以使模型更易于维护和灵活。大多数复杂的业务逻辑都进入了写入模型。读取模型可以相对简单。
- 更简单的查询。通过在读取数据库中存储物化视图,应用程序可以在查询时避免复杂的连接。
CQRS的实施问题和注意事项
- 复杂性。CQRS的基本思想很简单。但它可能导致更复杂的应用程序设计,特别是如果它们包含事件溯源模式。
- 消息传递。尽管 CQRS 不需要消息传递,但通常使用消息传递来处理命令和发布更新事件。在这种情况下,应用程序必须处理消息失败或重复消息。
- 最终一致性。如果将读写数据库分开,读取的数据可能会过时。必须更新读取模型存储以反映写入模型存储的更改,并且很难检测用户何时基于过时的读取数据发出请求。
何时使用CQRS?
在以下情况下考虑CQRS:
- 许多用户并行访问相同数据的协作域。CQRS 允许您定义具有足够粒度的命令,以最大限度地减少域级别的合并冲突,并且可以通过命令合并确实出现的冲突。
- 基于任务的用户界面,用户可以通过一系列步骤或复杂的域模型来引导用户完成复杂的过程。写入模型具有完整的命令处理堆栈,包括业务逻辑、输入验证和业务验证。写入模型可以将