架构设计系列文章,请参见连接。
介绍
命令查询责任分离源于Bertrand Mayer设计的命令查询分离(CQS)原理。CQS声明一个类只能有两种方法:改变状态并返回void的方法和返回状态但不改变它的方法。后来经过Greg Young的发展与推广最终形成了现在的CQRS。
讲解
命令查询的责任分离(Command Query Responsibility Segregation,简称CQRS)模式包含着两部分:能够使改变模型的状态的命令和模型状态的查询。CQRS是DDD应用领域的一个模式,主要解决DDD在数据库报表输出上处理方式。
在DDD架构中,通常会将查询和命令操作分开,具体落地时,是否将查询和命令分开成为两个项目可以视情况而定,大多数情况下放在一个项目可以提高业务内聚性。也可以在逻辑层面上划分为两个不同的操作模型(Command和Query)但是在物理层面上还是使用同一个数据库进行。
对于CQRS来说最主要的是改变状态和获取状态的两类操作,只要将这两类动作分离的都可以称作是CQRS。这样拆离之后对于查询DTO和命令DTO就也可以分离出来。大多数时候,改变状态所需的数据在形式或数量上都不同于用户需要查询所需的数据。使用相同的模型来一起处理查询和命令会会导致模型膨胀,只依靠一种类型来操作所需的所有东西,模型复杂性也会增加,聚合大小通常会更大。
模式描述
对于命令查询职责分离模式可以有两种变种模式:CQRS,CQRS/ES。CQRS是对命令和查询使用不同的服务器。而CQRS/ES是使用溯源事件的方式将用户命令发送到读数据库中。Event Sourcing是由Martin Fowler提出,是将业务领域精髓(尤其是最复杂的)与技术平台的复杂性实现脱钩的天作之合。为什么要用Event Sourcing?或 Domain Events – 救世主
在这两种模式的选择中也分为有两个阵营:一个说你应该总是使用CQRS / ES,另一个说你应该只使用你的解决方案的一部分,并且只有当你需要具有高性能/可用性/可扩展性系统的高度并发系统时。您应该始终根据您的要求评估您的选择。
CQRS使我们能够使用不同的模型来改变状态和不同的模型来支持查询。通常写操作的频率低于读操作。 具有单独的模型和分离的数据库引擎允许我们独立地扩展查询端并更好地处理并发访问,因为读取端不再堵塞写入或命令端(在相反的情况下)。
对于读写数据库数据结构不一致或纯粹不一致的数据库的情况下,可以通过Event Sourcing的方式进行支撑。并且Event Sourcing的方式还可以进行消息记录。
特点
-
开发
过程管理(康威定律)
CQRS/ES增加了平台的复杂度。需要在实施过程中以过程的方法解决复杂度增加造成的问题。可测试性
CQRS/ES的测试点较多。并且因为复杂的增加可能会造成测试过程中问题反复。可扩展性
CQRS/ES最主要的目标就是为了高性能/可用性/可扩展性系统而设计的。所以对于可扩展性的支持较好。
-
运维
可伸缩
CQRS/ES最主要的目标就是为了高性能/可用性/可扩展性系统而设计的。所以对于可伸缩性的支持较好。部署难易
CQRS/ES系统中涉及到多服务部署的问题,需要在上线时进行配置。维护难易
稳定性尚可,但是可跟踪性比较弱。所以维护难度比较高。
-
性能
CQRS/ES最主要的目标就是为了高性能/可用性/可扩展性系统而设计的。所以对于性能的支持较好。
总结:
在互联网高并发的情况下经常使用CQRS架构作为整体架构,然后再在CQRS内部使用其他的架构模式配合形成一套完整的架构。帮我们解决了很多关于性能、稳定性、数据拆分的问题。对于CQRS的特点可以总结为将用户操作与页面展示分离,可以使用静态化、缓存的方式解决读速度的问题。所以在CQRS中并没有限制在系统中使用同构数据库/数据源作为数据存储与查询做管理。在结合Event Sourcing的方式进行数据的更新操作。可以满足系统大量查询的情况。
参考
CQRS
领域驱动设计模式、原理与实践
CQRS架构
解决CQRS中的复杂问题
最全面的CQRS和事件溯源介绍 - Software House ASC