架构设计之解析CQRS架构模式!

文章首发到公众号:月伴飞鱼

文章内容收录到个人网站,方便阅读:http://hardyfish.top/

文章内容收录到个人网站,方便阅读:http://hardyfish.top/

文章内容收录到个人网站,方便阅读:http://hardyfish.top/

在这里插入图片描述

CQRS叫命令查询职责分离,事实上就是读写分离的意思。

  • 不过这里的读写分离和我们通常所理解的数据库级别的读写分离是两个不同的概念。

CQRS指的读写分离是指在应用程序内部的代码级别的读写分离。

在本文中,我将对此做出详细解释。

CQS思想

CQS:命令和查询分离:Command and Query Segregation

其核心思想是在任何一个对象的方法可以划分为两类:

  • 查询:获取数据,返回查询数据,但不改变数据状态。
  • 命令:改变数据状态,不返回任何数据。

CQRS模式的核心设计理念来自于一条设计原则,即单一职责原则

  • 所谓单一职责原则,指的是一个技术组件只应该负责具体一项职责。
    • 而不应该有多个导致该组件发生状态变化的操作。

基于CQS的思想,任何一个方法都可以拆分为命令和查询两部分,如下:

private int data = 0;
private int update(int value) {data += value;return data;
}

上述方法既改变了数据,又返回了数据状态。

如果按照CQS的思想,则该方法可以拆成CommandQuery两部分,如下:

private void update(int value) {data += value;
}
private int query() {return data;
}

对于命令侧是否返回数据实际业务诉求中并不一定能够完全统一。

比如:

  • 某些业务场景下可能会有返回业务主键的诉求,比如下单操作返回订单号。

基本原则

CQS的主要原则是:

  • 一个方法要么是命令,要么是查询,但不能两者兼有。
  • 这种分离有助于提高代码的可读性和维护性,因为它明确了方法的用途。

CQRS架构

Command and Query Responsibility Segregation

  • 即命令查询职责分离,是一种将命令和查询的责任明确分离的架构模式。
  • 这种模式进一步扩展了CQS的思想,适用于更大规模的系统架构。

架构思想:

CQRS将系统的读操作和写操作分离到不同的模型中:

  • 命令模型(Command Model):
    • 处理数据的写操作(创建、更新、删除)。
  • 查询模型(Query Model):
    • 处理数据的读操作(查询)。

这种分离可以通过不同的数据模型、数据库甚至服务来实现,从而优化读写性能和可伸缩性。

CQRS 模式的应用非常简单,如下图所示:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

假设服务为 UserService,在非CQRS模式下同时包含了查询和更新服务接口。

public class UserService {//  根据id查询用户UserId getUserId(int userId);// 更新用户void updateUser(User user);
}

应用CQRS模式之后的UserService被拆分成了两个接口,分别承担查询和写职责。

/**命令服务
*/
public class UserCommandService {void updateUser(UserCommand command);
}
/**查询服务
*/
public class UserQueryService{User getUserById(int userId);
}

最终一致性

采用CQRS后,查询和命令两侧通常会采用独立的数据模型

  • 采用CQRS模式并没有强制要求必须要进行数据模型的分离。

在这种架构模式下,命令侧的数据变化后及时同步(事件、消息队列)到查询侧,两侧数据并非实时。

  • 在一定的延时后两侧数据最终达成一致。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

最后总结

CQRS的使用者可以根据实际情况,将读写分离开单独部署,然后引入领域事件,使用消息队列做通信。

  • 但是这些都是基于不同业务场景的架构选择,而非CQRS本身的要求。
  • 实际上CQRS只是一种非常简单的模式而已,并没有和事件、消息队列这些有强关联。

读写分离部署+消息通信:

  • 会带来额外的系统复杂性和更高的运维成本。

《重构:改善既有代码的设计》的作者也提醒要小心使用CQRS,不推荐将CQRS复杂化处理。

参考资料:

  • CQRS 模式

  • 在微服务中应用简化后的 CQRS 和 DDD 模式

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/441073.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【可视化大屏】Python Flask框架介绍

为了能显示真实数据,使用flask快速搭建了一个web应用,然后连接数据库,读取数据库里的数据来进行大屏可视化显示(btw:数据是从车主之家网站上爬虫爬的) 家人们!记得使用专业版的pycharm&#xf…

保证文件只能在公司打开,走出公司就打不开这一神操作如何实现?一文告诉你详情!

在现代企业中,信息安全已经成为一项至关重要的任务。随着企业数据量的不断增加,如何确保敏感信息不被泄露成为企业面临的重要挑战。 其中,一种常见的需求是确保文件只能在公司内部环境中打开,一旦离开公司就无法访问。 本文将详…

计算机组成原理实验三 数据寄存器组R0..R3, MAR, ST, OUT

实验目的和要求 目的:了解模型机中各种寄存器结构、工作原理及其控制方法。 要求:利用CP226 实验系统上的K16..K23 开关做为DBUS 的数据,其它开关做为控制信号,将数据写入寄存器,数据寄存器组R0..R3,地址…

stm32开发环境的配置

keli5的安装 安装上以后,用管理员身份打开软件 复制里面的CID到破解软件里面 将Target调到ARM,然后生成 将注册码复制进软件那个界面,然后AddLIC就破解成功了 调试工具STLink驱动的安装 如果发现带感叹号代表驱动没有安装,但是设…

JavaEE之多线程进阶-面试问题

一.常见的锁策略 锁策略不是指某一个具体的锁,所有的锁都可以往这些锁策略中套 1.悲观锁与乐观锁 预测所冲突的概率是否高,悲观锁为预测锁冲突的概率较高,乐观锁为预测锁冲突的概率更低。 2.重量级锁和轻量级锁 从加锁的开销角度判断&am…

【Python时序预测系列】基于GRU模型实现多变量时间序列预测(案例+源码)

这是我的第363篇原创文章。 一、引言 单站点多变量单步预测问题----基于GRU实现多变量时间序列预测股票价格。 二、实现过程 2.1 读取数据集 dfpd.read_csv("data.csv", parse_dates["Date"], index_col[0]) print(df.shape) print(df.head()) fea_num …

OJ在线评测系统 微服务 OpenFeign调整后端下 nacos注册中心配置 不给前端调用的代码 全局引入负载均衡器

OpenFeign内部调用二 4.修改各业务服务的调用代码为feignClient 开启nacos注册 把Client变成bean 该服务仅内部调用,不是给前端的 将某个服务标记为“内部调用”的目的主要有以下几个方面: 安全性: 内部API通常不对外部用户公开,这样可以防止…

【目标检测】木制地板缺陷破损数据集338张6类VOC+YOLO格式

数据集格式:Pascal VOC格式YOLO格式(不包含分割路径的txt文件,仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数):3383 标注数量(xml文件个数):3383 标注数量(txt文件个数):3383 标注…

python爬虫案例——处理验证码登录网站(12)

文章目录 前言1、任务目标2、网页分析3、代码编写4、第三方验证码识别平台(超级鹰)前言 我们在爬取某些网站数据时,可能会遇到必须登陆才能获取网页内容的情况,而大部分网站登录都需要输入验证码才能登录成功,所以接下来我将会通过实际案例来讲解如何实现验证码登录网站 1…

前后端分离开发YApid

开头先声明以下,这篇主要用于概念的介绍…… 在当今的互联网应用开发中,前后端分离逐渐成为主流的开发模式。相比于传统的前后端混合开发,这种新模式在灵活性、可维护性和团队协作等方面具有显著优势。 前后端混合开发 在前后端混合开发模式…

气膜淤泥加工厂:创新土壤修复的绿色方案—轻空间

随着城市化进程的加快,土壤污染问题日益严重,淤泥处理成为环保领域亟待解决的重要课题。气膜淤泥加工厂应运而生,提供了一种高效、环保的解决方案,为土壤修复和环境保护注入了新的活力。 高效处理,保障环境安全 气膜淤…

什么是 HTTP 请求中的 options 请求?

在 Chrome 开发者工具中的 Network 面板看到的 HTTP 方法 OPTIONS,其实是 HTTP 协议的一部分,用于客户端和服务器之间进行“预检”或“协商”。OPTIONS 请求的作用是让客户端能够获取关于服务器支持的 HTTP 方法和其他跨域资源共享 (CORS) 相关的信息&am…

2-112基于matlab的协同干扰功率分配模型

基于matlab的协同干扰功率分配模型,带操作界面的功率分配GUI,可以实现对已有功率的分配优化,可以手动输入参数值。4个干扰山区分二批总干扰功率,每个扇区包括威胁总系数、综合压制概率、目标函数增量等。程序已调通,可…

Linux:进程调度算法和进程地址空间

✨✨✨学习的道路很枯燥,希望我们能并肩走下来! 文章目录 目录 文章目录 前言 一 进程调度算法 1.1 进程队列数据结构 1.2 优先级 ​编辑 1.3 活动队列 ​编辑 1.4 过期队列 1.5 active指针和expired指针 1.6 进程连接 二 进程地址空间 2.1 …

HCIP--以太网交换安全(二)

端口安全 一、端口安全概述 1.1、端口安全概述:端口安全是一种网络设备防护措施,通过将接口学习的MAC地址设为安全地址防止非法用户通信。 1.2、端口安全原理: 类型 定义 特点 安全动态MAC地址 使能端口而未是能Stichy MAC功能是转换的…

Day8:返回倒数第k个节点

题目: 实现一种算法,找出单向链表中倒数第k个节点。返回该结点的值。 示例: 输入:1->2->3->4->5和k2 输出:4 说明: 给定的k保证是有效的。 public int kthToLast(ListNode head,int k){…

【STM32-HAL库】AHT10温湿度传感器使用(STM32F407ZGT6配置i2c)(附带工程下载连接)

一、温湿度传感器: 温湿度传感器是一种能够检测环境中的温度和湿度,并将其转化为电信号输出的装置。它在智能家居、工业自动化、气象监测、农业等领域有着广泛的应用。 原理: 温湿度传感器通常基于不同的物理原理,以下是一些常见…

前端vue-配置基地址并发送请求

1.首先,在HBuilder的终端下载安装luch-request 2.创建一个目录utils,以及下面的http.js文件,导入安装包,在new一下request,配置接口的基地址 3.在测试文件目录里面进行测试,看看请求能否发送成功&#xff…

Activity

文章目录 1.启停活动页面1.Activity启动和结束2.Activity生命周期3. Activity启动模式 2.在活动之间传递信息1.显示Intent和隐式Intent显示Intent隐式Intent 2.向下一个Activity发送数据3.向上一个Activity返回数据 3.为活动补充附加信息1.利用资源文件配置字符串2.利用元数据传…

零基础入门AI大模型应用开发,你需要一个系统的学习路径!

前言 随着人工智能技术的迅猛发展,特别是在大型语言模型(LLMs)领域的突破,AI大模型已经成为当今科技领域的热门话题。不论是对于希望转型进入AI行业的职场人士,还是对未来充满憧憬的学生,掌握AI大模型的应…