发布网友 发布时间:2024-10-02 12:18
共1个回答
热心网友 时间:2024-10-18 19:37
软件设计是不断发展与进化的过程。系统从简单到复杂,每一次进阶都伴随着对技术的选择与考量。作为架构师或高级工程师,我们需要在开发进度、技术堆栈、团队水平等多种因素间找到平衡,以确保解决方案的可行性和合理性。
本文旨在介绍CQRS(Command Query Responsibility Segmentation)的核心概念及其解决的问题。我们将通过一个从单体架构到CQRS的演进过程,探讨每一步背后的原因和方法。
传统单体架构是最常见的系统设计模式。它由API服务器和数据库组成,使用RESTful API进行通信。数据传输通过数据传输对象DTO进行,客户端与后端协商传输格式。在写操作中,客户端将DTO发送给后端进行CRUD操作,后端将DTO转化为领域对象存储。读操作则直接通过API获取DTO。
为了解决性能优化问题,引入了读/写拆分策略。写路径专注于数据持久化,读路径专注于数据查询。在写路径中,客户端向后端发送DTO进行CRUD操作,后端通过响应(成功或失败)反馈给客户端。读路径则简单地通过API获取DTO。在客户端,DTO表示在屏幕上呈现的所有数据,如社交媒体个人资料中的姓名、活动等信息。
读/写拆分是必要的,因为它允许我们针对读和写操作优化系统。在写路径上,我们可以进行缓存操作以减少响应时间;在读路径上,可以使用只读缓存减少数据获取时间。同时,通过异步处理写操作,可以使用消息队列和Worker处理大量写入数据。此外,不同数据库可以同时用于写入和读取,以实现更好的性能和扩展性。
虽然传统单体架构提供了基本的系统功能,但存在两个主要问题:缺乏领域概念和可扩展性*。引入域概念后,消息代替了DTO,使得系统能够更有效地处理特定领域的操作。但读路径仍然需要DTO,以处理需要显示在屏幕上的信息。这导致了在读取路径上进行大量处理以获取DTO,从而增加了系统复杂性。
CQS旨在解决读/写拆分带来的痛点。在读取路径中,应用服务负责生成预先构建的DTO,以简化客户端请求和数据库查询。生成这些DTO的责任在写路径,它需要持久化领域对象和DTO。这样,读取路径应用服务变得更加简单,专注于分页、排序等工作。
在CQRS架构中,数据从客户端开始,以命令格式进入系统。通过业务逻辑,将命令转化为领域对象存储。领域对象转换成各种读取视图,并存储在不同的数据库中。最后,客户端通过DTO形式获取这些读取视图。
虽然CQRS解决了领域和性能问题,但也带来了数据一致性挑战。实现最终一致性的方法包括事件溯源和混合方法。事件溯源通过顺序存储消息来构建读取视图,而混合方法结合了状态和事件的保留,根据实际情况选择数据源。
系统设计没有万能方案,每次进阶都是为了解决特定问题。CQRS似乎解决了提到的局限性,但同时也引入了新的挑战。技术选择总是伴随着取舍,关键在于充分了解每个选项的风险与收益,从而做出相对合理的决策。
CQRS相对简单,它提供了一种从系统演化过程出发,理解系统设计与问题解决方式的方法。通过本文的分析,你可以看到,DDD概念并不复杂,而是旨在封装业务逻辑,方便扩展功能需求。CQRS则是一个技术决策的过程,它简化了系统设计,有助于解决实际问题。