当前位置: 首页 > news >正文

DDD - 六边形架构和CQRS架构

DDD - 六边形架构和CQRS架构

  • 1. 六边形架构
  • 2. CQRS
    • 2.1 什么是CQRS
    • 2.2 采用CQRS架构的一个前提
    • 2.3 实现方式
    • 2.4 CQRS的适用场景
    • 2.5 CQRS架构的数据流
    • 2.6 CQRS\ES - 架构演进

1. 六边形架构

六边形架构又称为端口-适配器,这个名字更容器理解。六边形架构将系统分为内部(内部六边形)和外部,内部代表了应用的业务逻辑,外部代表应用的驱动逻辑、基础设施或其他应用。内部通过端口和外部系统通信,端口代表了一定协议,以API呈现。一个端口可能对应多个外部系统,不同的外部系统需要使用不同的适配器,适配器负责对协议进行转换。这样就使得应用程序能够以一致的方式被用户、程序、自动化测试、批处理脚本所驱动,并且,可以在与实际运行的设备和数据库相隔离的情况下开发和测试。

六边形架构的核心理念是:应用是通过端口与外部进行交互的

在下图的六边形架构中,红圈内的核心业务逻辑(应用程序和领域模型)与外部资源(包括 APP、Web 应用以及数据库资源等)完全隔离,仅通过适配器进行交互。它解决了业务逻辑与用户界面的代码交错问题,很好地实现了前后端分离。六边形架构各层的依赖关系是由外向内依赖的。

在这里插入图片描述

六边形架构将系统分为内六边形和外六边形两层,这两层的职能划分如下:

  • 红圈内的六边形实现应用的核心业务逻辑;
  • 外六边形完成外部应用、驱动和基础资源等的交互和访问,对前端应用以 API 主动适配的方式提供服务,对基础资源以依赖倒置被动适配的方式实现资源访问。

六边形架构的一个端口可能对应多个外部系统,不同的外部系统也可能会使用不同的适配器,由适配器负责协议转换。这就使得应用程序能够以一致的方式被用户、程序、自动化测试和批处理脚本使用。

2. CQRS

2.1 什么是CQRS

CQRS,作为一种战术办法,是实现DDD建模领域的最佳途径之一。事实上,它就是因为这个目标而诞生在这个世界上。

在这里插入图片描述

CQRS本身只是一个读写分离的架构思想,全称是:Command Query Responsibility Segregation,即命令查询职责分离,表示在架构层面,将一个系统分为写入(命令)和查询两部分。一个命令表示一种意图,表示命令系统做什么修改,命令的执行结果通常不需要返回;一个查询表示向系统查询数据并返回

CQRS架构中,另外一个重要的概念就是事件,事件表示命令操作领域中的聚合根,然后聚合根的状态发生变化后产生的事件。

2.2 采用CQRS架构的一个前提

由于CQRS架构的一致性模型为最终一致性,所以,你的系统要接受查询到的数据可能不是最新的,而是有几个毫秒的延迟。之所以会有这个前提,是因为CQRS架构考虑到,作为一个多用户同时访问的互联网应用,当在高并发修改数据的情况下,比如秒杀、12306购票等场景,用户UI上看到的数据总是旧的。比如你秒杀时提交订单前看到库存还大于0,但是当你提交订单时,系统提示你宝贝卖完了。这个就说明,在这种高并发修改同一资源的情况下,任何人看到的数据总是Stale的,即旧的。

2.3 实现方式

CQRS作为一种架构思想,可以有多种实现方式:

  • 最常见的CQRS架构是数据库的读写分离

  • 系统底层存储不分离,但是上层逻辑代码分离

  • 系统底层存储分离,C 端采用 Event Sourcing 的技术,在 EventStore 中存储事件;Q 端存储对象的最新状态,用于提供查询支持;

Event Sourcing - 事件溯源:

  • 不保存对象的最新状态,而是保存对象产生的所有事件;
  • 通过事件溯源(Event Sourcing, ES)得到对象最新状态。

2.4 CQRS的适用场景

在这里插入图片描述

  1. 当我们的应用的写模型和读模型差别比较大时;

  2. 当我们希望实践DDD时;因为CQRS架构可以让我们实现领域模型不受任何ORM框架带来的对象和数据库的阻抗失衡的影响;

  3. 当我们希望对系统的查询性能和写入性能分开进行优化时,尤其是读/写比非常高的系统,CQ分离是必须的;

  4. 当我们希望我们的系统同时满足高并发的写、高并发的读的时候;因为CQRS架构可以做到C端最大化的写,Q端非常方便的提供可扩展的读模型。

这里我主要分享的CQRS架构是上面第3种实现方式,也就是上图所画的架构。在我心目中,只有第三种才是真正意义上的CQRS架构。

2.5 CQRS架构的数据流

C 端的命令的执行流程

客户端如(MVC Controller)发送命令通知系统做修改:

  1. 发送命令到分布式MQ;
  2. 然后命令的订阅者处理命令;
  3. 订阅者内部根据不同的命令调用不同的 Command Handler 进行处理;
  4. Command Handler 内部根据命令所指定的聚合根 ID 从 In-Memory 内存中直接获取聚合根对象的引用,然后操作聚合根对象;
  5. 聚合根对象状态发生变化并产生事件;
  6. 框架负责自动持久化事件到 Event Storage(简称EventStore);
  7. 框架负责将事件发布到 Event MQ;
  8. Event 订阅者订阅事件,然后调用对应的 Event Handler 进行处理,如更新 Data Storage(保存了聚合根的最新状态,通常叫读库,ReadDB)。

Q端的查询的执行流程

客户端如(MVC Controller)发出查询请求系统返回数据:

  1. 调用轻薄的 Query Service,传如 Query DTO;
  2. Query Service 从读库进行查询并返回结果。

读库可以有很多种,依据我们的业务场景来选择:比如关系型DB、分布式缓存等NoSQL、搜索引擎,etc。

2.6 CQRS\ES - 架构演进

在这里插入图片描述

相关文章:

  • 宠物寄养小程序实战教程02
  • 【计算机网络】运输层习题(谢希仁)(1)
  • 微信小程序抓包-夜神模拟器结合BurpSuite抓包(可用于现在最新版本微信)
  • SAR/毫米波雷达 论文阅读 | Freehand, Agile, and High-Resolution Imaging, IEEE Access 2019
  • 神经网络一词在英文中是,网络词神经质什么意思
  • KOOM原理讲解(上)-JAVA内存分析
  • create-vite‘ 不是内部或外部命令,也不是可运行的程序
  • 【JS】牛客专项练习01
  • 计算机组成原理 | 总线
  • 简单神经网络算法原理,最简单的神经网络算法
  • 【在线教育】POI入门
  • 浅析RocketMQ-存储文件
  • 【JAVA】继承和多态的子类和父类代码执行顺序研究
  • ConcurrentHashMap put和扩容的源码深度解析(内含JDK8中3个bug以及修复的版本)
  • 广义线性混合模型(GLMM)变量选择
  • [deviceone开发]-do_Webview的基本示例
  • 「前端早读君006」移动开发必备:那些玩转H5的小技巧
  • 【162天】黑马程序员27天视频学习笔记【Day02-上】
  • 【402天】跃迁之路——程序员高效学习方法论探索系列(实验阶段159-2018.03.14)...
  • 【跃迁之路】【669天】程序员高效学习方法论探索系列(实验阶段426-2018.12.13)...
  • angular2开源库收集
  • Apache的基本使用
  • cookie和session
  • docker-consul
  • HTTP请求重发
  • Java基本数据类型之Number
  • Java知识点总结(JDBC-连接步骤及CRUD)
  • Laravel Telescope:优雅的应用调试工具
  • Meteor的表单提交:Form
  • Netty 框架总结「ChannelHandler 及 EventLoop」
  • PHP CLI应用的调试原理
  • Python打包系统简单入门
  • thinkphp5.1 easywechat4 微信第三方开放平台
  • Vue UI框架库开发介绍
  • vue.js框架原理浅析
  • 聚类分析——Kmeans
  • 前端面试题总结
  • 试着探索高并发下的系统架构面貌
  • 异步
  • - 语言经验 - 《c++的高性能内存管理库tcmalloc和jemalloc》
  • !!Dom4j 学习笔记
  • # Python csv、xlsx、json、二进制(MP3) 文件读写基本使用
  • #1014 : Trie树
  • (007)XHTML文档之标题——h1~h6
  • (13):Silverlight 2 数据与通信之WebRequest
  • (android 地图实战开发)3 在地图上显示当前位置和自定义银行位置
  • (C语言)求出1,2,5三个数不同个数组合为100的组合个数
  • (Redis使用系列) SpirngBoot中关于Redis的值的各种方式的存储与取出 三
  • (附源码)spring boot车辆管理系统 毕业设计 031034
  • (附源码)计算机毕业设计高校学生选课系统
  • (四)图像的%2线性拉伸
  • (一)基于IDEA的JAVA基础12
  • (转)jdk与jre的区别
  • (转)scrum常见工具列表
  • .NET CLR基本术语