命令查询职责分离 (CQRS)

news2024/11/30 10:43:44

CQRS 的最初需求

多年来,传统的 CRUD(创建、读取、更新、删除)模式一直是系统架构的支柱。在 CRUD 中,读取和写入操作通常由相同的数据模型和相同的数据库模式处理。虽然这种方法简单直观,但随着系统规模的扩大和需求变得更加复杂,它的效率就会降低。

例如,考虑一个拥有数百万用户的大型电子商务应用程序。该系统可能面临相互冲突的需求:它需要快速读取产品详细信息、评论和用户配置文件,但它还必须有效处理数千笔交易、库存更新和订单下达。随着读取和写入操作的增长,对两者使用单一模型可能会导致瓶颈,影响性能和用户体验。

CQRS 模式的基础知识

CQRS 的引入是为了解决这些扩展挑战。该模式的本质就在于它的名字——命令查询职责分离。在这里,命令负责系统状态的任何更改(例如下订单或更新用户配置文件),而查询则处理数据检索,没有任何副作用。

在 CQRS 系统中,这两个操作被视为完全不同的职责,通常具有单独的数据模型、数据库,甚至单独的服务器或服务。这使得每个操作都可以独立于另一个进行调整、缩放和维护,并与每个操作的特定需求保持一致。

CQRS 组件

命令

命令是在系统内执行操作或更改的指令组件。它们的命名应反映意图和上下文,例如PlaceOrder或UpdateUserProfile。重要的是,命令应该负责更改,因此不应返回数据。进一步探索命令如何处理验证、授权和业务逻辑将阐明它们在 CQRS 模式中的角色。

查询

另一方面,查询处理所有数据请求操作。重点可能在于如何构建这些来提供针对特定用例定制的优化的、非规范化的数据视图。您可以深入研究构建和优化查询服务的不同策略,以处理潜在的复杂读取模型。

命令和查询处理程序

处理程序充当促进命令和查询执行的代理。命令处理程序负责执行与数据突变相关的逻辑,同时确保遵守验证和业务规则。查询处理程序管理数据的检索,可能涉及复杂的聚合或连接以形成请求的读取模型。

单数据库与双数据库方法

单一数据库

在此模型中,命令和查询操作都在单个数据库上执行,但具有不同的模型或模式。即使这两个操作共享相同的物理存储,它们也可能使用针对其特定要求而优化的不同表、视图或索引。

它可以表示如下:

图片

好处

  • 简化基础设施并减少开销

  • 立即一致性,因为写入和读取操作之间没有延迟

权衡

  • 在大量并发操作期间,共享资源仍然可能成为瓶颈。

  • 独立调整和缩放操作的灵活性较低

双数据库方法

在这里,命令和查询操作完全分开,使用两个不同的数据库或存储系统。写数据库专用于处理命令,而读数据库则服务于查询操作。必须添加手柄同步系统。

它可以表示如下:

图片

好处

  • 每个操作的单独调整、缩放和优化

  • 每个数据库有可能托管在不同的服务器或服务上,分配负载;数据库解决方案也可能有所不同,以便为特定需求提供更多的模块化。

权衡

  • 为确保两个数据库之间的数据一致性带来了复杂性

  • 需要同步机制来桥接写入和读取数据库之间潜在的错位或延迟:例如,写入操作可能会更新命令数据库,但读取数据库可能不会立即反映这些更改。为了解决这个问题,同步技术的范围可以从简单的轮询到更复杂的方法,例如事件源,其中修改被捕获为一系列事件并重放以更新读取的数据库。

单一数据库方法提供了简单性;双数据库配置提供了更大的灵活性和可扩展性,但代价是增加了复杂性。这些方法之间的选择取决于相关系统的具体要求和挑战,特别是围绕性能需求和一致性要求。

CQRS 模式的优点和权衡

好处

  • 性能优化:通过分离读写逻辑,可以独立扩展和优化各个方面。例如,如果系统读取量很大,您可以分配更多资源来处理查询,而不会因写入操作的需求而陷入困境。

  • 灵活性和可扩展性:通过单独的读取和写入模型,可以更轻松地在一个模型中引入更改,而不会影响另一个模型。这种隔离不仅可以实现更敏捷的开发和更轻松的可扩展性,还可以针对与急切实体加载相关的常见问题提供保护。通过明确地处理读取和写入,可以优化系统以避免不必要的数据加载,从而提高性能并减少资源消耗。

  • 简化的代码库:分离命令和查询逻辑可以使代码库更易于维护且不易出错。每个模型都有明确的职责,减少了由于相互交织的逻辑而引入错误的可能性。

权衡

  • 数据一致性:由于读写模型可能不同,实现数据一致性可能具有挑战性。CQRS 通常与“最终一致性”模型齐头并进,这可能并不适合所有应用程序。

  • 复杂性开销:引入 CQRS 会增加复杂性,尤其是与事件溯源等其他模式配合使用时。评估所获得的好处是否超过增加的复杂性至关重要。

  • 增加开发工作量:拥有独立的读写模型本质上意味着维护系统的两个不同部分。这会增加初始开发工作量以及持续的维护开销。

结论

CQRS 提供了一种变革性的数据管理方法,在性能、可扩展性和代码清晰度方面带来了显着的优势。然而,这并不是灵丹妙药。与所有架构决策一样,采用 CQRS 应该是一个经过深思熟虑的选择,要考虑到它的好处和它带来的挑战。对于可扩展性和性能至关重要且可以接受权衡的系统,CQRS 可以改变游戏规则,将系统的稳健性和响应能力提升到新的高度。


作者:Artem Artemev

更多技术干货请关注公号【云原生数据库

squids.cn,云数据库RDS,迁移工具DBMotion,云备份DBTwin等数据库生态工具。

irds.cn,多数据库管理平台(私有云)。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

四、IDEA创建项目时,Maven Archetype模板工程说明

什么是Maven Archetype Archetype是一个Maven项目的模板工具包,它定义了一类项目的基本架构。Archetype为开发人员提供了创建Maven项目的模板,同时它也可以根据已有的Maven项目生成参数化的模板。 官方文档:https://maven.apache.org/archet…

Redis面试题:redis做为缓存,mysql的数据如何与redis进行同步呢?(双写一致性)

目录 强一致性:延迟双删,读写锁。 弱一致性:使用MQ或者canal实现异步通知 面试官:redis做为缓存,mysql的数据如何与redis进行同步呢?(双写一致性) 候选人:嗯&#xff…

C++ 数据结构之-最小栈(MinStack)

最小栈 最小栈(Min Stack)是一个支持常数时间复杂度获取栈中最小元素的特殊栈数据结构。通常,标准的栈数据结构只支持在常数时间内执行入栈(push)和出栈(pop)操作,但无法在常数时间内…

痤疮分类-yolov5 学习过程

1、在github上下载yolov5-5.0的源码。 GitHub - ultralytics/yolov5: YOLOv5 🚀 in PyTorch > ONNX > CoreML > TFLite

第一百七十九回 自定义SlideImageSwitch

文章目录 1. 概念介绍2. 思路与方法2.1 实现思路 3. 代码与效果3.1 示例代码3.2 运行效果 4. 内容总结 我们在上一章回中介绍了"SlideSwitch组件"相关的内容,本章回中将介绍自定义SlideImageSwitch.闲话休提,让我们一起Talk Flutter吧。 1. 概…

JVM——几种常见的对象引用

目录 1. 软引用软引用的使用场景-缓存 2.弱引用3.虚引用和终结器引用 可达性算法中描述的对象引用,一般指的是强引用,即是GCRoot对象对普通对象有引用关系,只要这层关系存在, 普通对象就不会被回收。除了强引用之外,Ja…

bugku 渗透测试

场景1 查看源代码 场景2 用dirsearch扫描一下看看 ok看到登录的照应了第一个提示 进去看看 不出所料 随便试试admin/admin进去了 在基本设置里面看到falg 场景3 确实是没啥想法了 找到php在线运行 检查网络,我们发现这个php在线运行会写入文件 那我们是不是写…

WPS AI初体验

1、启动AI 2、输入需要创作的内容 3、创作的内容展示 当然,以下是一份经过润色后的年终总结目录: 一、引言 1. 总结的目的和意义 2. 总结的范畴和覆盖范围 3. 总结的编写原则和标准 二、公司概览 1. 公司简介 2. 公司历史与现状 3. 公司组织架构和团队介…

C编译过程

寻觅GCC 如果你已经安装了Clion&#xff0c;那么gcc就在根目录下。 如果没有&#xff0c;那么需要去minGW的官网下载安装。添加到环境变量中。 编写C代码 #include <stdio.h>#define ARRAY_SIZE(a) sizeof(a)/sizeof(a[0]) static int a 123;int main() {int i 0;c…

Android逆向实战 - MIUI调起三方应用系统拦截弹窗分析

近期&#xff0c;发现在部分Android手机调起其他应用时&#xff0c;会弹出一个系统弹窗拦截调起&#xff0c;需要用户二次确认。经过内部众测&#xff0c;发现绝大多数是小米手机&#xff0c;而且跟Android版本没有直接关系&#xff0c;猜测是MIUI某次升级引入的功能。这篇文章…

如何在 Vim 中剪切、复制和粘贴

目录 前言 如何在 Vim 编辑器中复制文本 如何在 Vim 编辑器中剪切文本 如何在 Vim 编辑器中粘贴文本 如何通过选择文本来剪切和复制文本 通过选择文本复制 在 Vim 中选择文本来剪切文本 前言 在本篇 Vim 快速技巧中&#xff0c;你将学习到剪切和复制粘贴的相关知识。 剪…

Linux C语言 22-多进程

Linux C语言 22-进程 本节关键字&#xff1a;进程、exec函数族 相关C库函数&#xff1a;fork、getpid、getppid、getuid、geteuid、getgid、getegid、execl、execlp、execv、execvp、execle、execvpe 什么是进程&#xff1f; 进程是程序的执行过程&#xff1b;进程是动态的&…

WordPress安装AWS插件实现文本转语音功能

适用于 WordPress 的 AWS 插件示例演示了内容创建者如何轻松地为所有书面内容添加文本转语音功能。随着语音搜索的不断增加&#xff0c;以音频格式提供更多网站内容变得至关重要。通过添加语音功能&#xff0c;网站访客可以通过在线音频播放器和播客应用程序等新渠道使用您的内…

【代码】平抑风电波动的电-氢混合储能容量优化配置(完美复现)matlab-yalmip-cplex/gurobi

程序名称&#xff1a;平抑风电波动的电-氢混合储能容量优化配置 实现平台&#xff1a;matlab-yalmip-cplex/gurobi 代码简介&#xff1a;针对电-氢混合系统协同平抑接入新型电力系统的 新能源波动问题&#xff0c;提出考虑碱性电解槽运行特性的电-氢 混合储能容量优化配置方案…

鸿蒙开发报错:agconnect sdk not initialized. please call initialize()【BUG已解决】

文章目录 项目场景:问题描述原因分析:解决方案:总结:项目场景: 鸿蒙开发报错: agconnect sdk not initialized. please call initialize() 问题描述 报错内容为: 10-25 11:41:01.152 6076-16676 E A0c0d0/JSApp: app Log: 数据查询失败: {“code”:1100001,“messag…

Ps:拾色器 - 选取专色

在 Adobe 拾色器中&#xff0c;可点击“颜色库” Color Libraries按钮来选取专色。 首先在色库 Book列表中选择对应的色库&#xff0c;然后在中间的色相条中选择需要的样本组&#xff0c;再从左侧颜色列表中选取颜色。 可以直接键入颜色名称来选择。比如&#xff0c;键入 13&am…

解决视口动画插件jquery.aniview.js使用animate.css时无效的问题(最新版本网页视口动画插件的使用及没作用、没反应)

当网站页面元素进入视口时自动应用过渡效果。CSS过渡效果可以为网页添加动画效果&#xff0c;并提供了一种平滑的转换方式&#xff0c;使元素的变化更加流畅和生动。而通过jQuery插件来获取页面滚动位置决定合适调用动画效果。 一、官网 animate.css官网 一款强大的预设css3动…

MYSQL基础之【创建数据表,删除数据表】

文章目录 前言MySQL 创建数据表通过命令提示符创建表使用PHP脚本创建数据表 MySQL 删除数据表在命令提示窗口中删除数据表使用PHP脚本删除数据表 后言 前言 hello world欢迎来到前端的新世界 &#x1f61c;当前文章系列专栏&#xff1a;Mysql &#x1f431;‍&#x1f453;博主…

【数据结构实验】树(一)构建二叉查找树(BST)

文章目录 1. 引言2. 二叉查找树3. 实验内容3.1 实验题目&#xff08;一&#xff09;输入要求&#xff08;二&#xff09;输出要求 3.2 算法实现1. 数据结构2. 全局变量3. 中序遍历函数InOrder4. 二叉查找树的构建函数T5. 主函数 3.3 代码整合 4. 实验结果 1. 引言 二叉查找树&a…

公交路线查询系统

公交路线查询系统 一&#xff1a;目标一&#xff1a;类的定义构造方法 set和get方法&#xff1a;目标二&#xff1a;静态属性 静态方法 toString方法&#xff1a;目标三&#xff1a;抽象类的定义 抽象方法 实际应用&#xff1a;abstract class AbstractRoute{目标四&#xff1…