摘要

在之前的文章DDD-CQRS能解什么问题中,阐述了什么是CQRS。但是并没有业务需求可以应用CQRS。最近需要处理一个文本增量更新的业务,经过需求分析后,尝试使用CQRS来解这个问题

问题分析

一个文本页面编辑,对象很大,之前是全量保存。涉及到的网络传输对象比较大,经常超时OOM,所以交互改成,只保存修改的部分,也就是增量更新。

之前业务中没法使用CQRS,在于使用CQRS后,数据的维护变得异常麻烦。比如我对一个表单进行了反复修改,生成了N份历史修改数据,获取最新数据时需要对这些历史数据进行合并,变得异常麻烦。
这次业务能够使用在于,

  1. 拆分写,能够有效的减少数据传输。
  2. 读写可以分离,分别扩展
  3. 通过事件溯源,可以恢复数据到任意编辑的版本

具体设计

系统整体采用CQRS+Event-Sourcing来实现

CQRS

CQRS模式通过使用不同的接口来分离读取数据和更新数据的操作。CQRS模式可以最大化性能,扩展性以及安全性,
还会为系统的持续演化提供更多的弹性,防止Update命令在域模型Level发生冲突。

文本编辑这块领域模型很薄,没有什么领域校验与约束,按读取数据/更新数据分离,当读写压力不同时,以后可以拆分成不同的服务,分别扩展。

Event Sourcing(事件溯源)

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

系统整体分为三大部分

一. command

所有数据修改命令,更新Command、撤销Command、覆盖Command
会持久化存储到CommitRepository中。然后发出事件消息

二. event-handle

对于文本编辑这个case,事件处理主要是合并提交的command event。否则事件溯源时,需要处理的数据更新事件太多,耗时太长。

三. query

查询数据,能够根据修改记录获取任意commit的数据。

三大部分分离,可以部署为单个服务,也可以解耦为多个服务,便于扩展。

需要解决的问题

  1. 如何保证事件的有序性

CQRS的一个典型问题就是生产端的事件顺序和消费端的事件顺序不一致,导致数据不一致的问题。如何去解决呢?

Command处理部分处理所有的数据更新部分,会生成一个全局有序的commitid,代表着更新的顺序。也就是生产端的事件顺序,但是到达我们消费端的顺序却不一定是这个顺序。所以消费端,事件处理完成后,会更新消费的最新commitid。如果当前事件的commitid小于最新的commitid,事件遗弃。

  1. 如何保证读数据性能
    event handle部分会去合并commit,所以读数据不是从所有的修改数据commit中合并数据。数据已经预先处理了,所以会大大加快读取效率,可以控制待合并的数据在5~10commits范围之内。

  2. 数据会丢失吗

系统分离后,没有事务保证,数据的完整性如何保证。

当数据更新Command写入成功后,代表这条数据更新成功,这个数据就不会丢失。因为这些数据都已经被持久化了,剩下的问题就是读取这些提交的Command Commit。我们可以通过合并这些commit,得到最新的完整数据。所以即使event-handle部分宕机了,仍然可以读取到最新的数据。

说明

这个案例还是没有应用框架,调研过axon,评估目前还不是太适合用,代码可读性不强,带来的好处不明显。后续再考虑是否需要引入框架。

DDD系列

我们团队是如何落地DDD的(1)

可落地的DDD的(2)-为什么说MVC工程架构已经过时

可落地的DDD(3)-如何利用DDD进行微服务的划分

可落地的DDD(4)-如何利用DDD进行微服务的划分(2)

可落地的DDD(5)-战术设计

如何避免写出烂的业务代码(1)-领域对象与领域服务

如何避免写出烂的业务代码(2) DDD整改

DDD-CQRS能解什么问题

一次关于聚合根的激烈讨论

DDD-CQRS的落地案例的更多相关文章

  1. 【DDD/CQRS/微服务架构案例】在Ubuntu 14.04.4 LTS中运行WeText项目的服务端

    在<WeText项目:一个基于.NET实现的DDD.CQRS与微服务架构的演示案例>文章中,我介绍了自己用Visual Studio 2015(C# 6.0 with .NET Frame ...

  2. DDD CQRS和Event Sourcing的案例:足球比赛

    在12月11日新的有关DDD CQRS和Event Sourcing演讲:改变心态- 以更加面向对象视角看待业务领域建模中,作者以足球比赛football Match为案例说明传统编程方法和CQRS的 ...

  3. DDD/CQRS模式,微服务,容器

    DDD/CQRS模式,微服务,容器 https://docs.microsoft.com/zh-cn/previous-versions/msp-n-p/ee658109(v=pandp.10) We ...

  4. DDD领域驱动设计-案例建模设计-Ⅲ

    1. 背景 参考<DDD领域驱动设计-案例需求文档>,本文将构建实体,聚合根详述领域驱动中的建模设计.构建实体,聚合根的一些原则或方法,将在后续文章中说明. 2. 建模设计 2.1. 实体 ...

  5. 你一定看得懂的 DDD+CQRS+EDA+ES 核心思想与极简可运行代码示例

    前言 随着分布式架构微服务的兴起,DDD(领域驱动设计).CQRS(命令查询职责分离).EDA(事件驱动架构).ES(事件溯源)等概念也一并成为时下的火热概念,我也在早些时候阅读了一些大佬的分析文,学 ...

  6. 一款不错的 Go Server/API boilerplate,使用 K8S+DDD+CQRS+ES+gRPC 最佳实践构建

    Golang API Starter Kit 该项目的主要目的是使用最佳实践.DDD.CQRS.ES.gRPC 提供样板项目设置. 为开发和生产环境提供 kubernetes 配置.允许与反映生产的 ...

  7. DDD CQRS架构和传统架构的优缺点比较

    明天就是大年三十了,今天在家有空,想集中整理一下CQRS架构的特点以及相比传统架构的优缺点分析.先提前祝大家猴年新春快乐.万事如意.身体健康! 最近几年,在DDD的领域,我们经常会看到CQRS架构的概 ...

  8. 软件设计、DDD概念及落地时的一些零碎思考和记录

    DDD理解 DDD体现的是对现实的充分尊重. 1.尊重业务现实,领域专家.领域语言等概念 2.尊重团队现实 3.尊重变化 Application 对某一业务线的整体掌控,流程组装,进度管理,存储时机掌 ...

  9. 软件设计、DDD概念及落地时的一些零碎思考和记录2

    主要是项目中一些落地经验和记录 技术人员.开发人员 大部分程序员真的不善于沟通,经常会显得很保守: 他们技术上的困惑.误解乃至郁闷都很难直接的表达清楚: 他们对自己的错误"印象"很 ...

随机推荐

  1. FPGA之IO信号类型深入理解

    在FPGA设计开发中,很多场合会遇到同一根信号既可以是输入信号,又可以是输出信号,即IO类型(Verilog定义成inout). 对于inout型的信号,我们既可以使用FPGA原语来实现,也可以使用V ...

  2. 一文MyBatis-Plus快速入门

    目录 一.依赖及配置 1.在idea中创建一个SpringBoot项目,在pom.xml中添需要的依赖 2.配置数据库连接 3.在启动类中添加注解 @MapperScan 扫描Mapper接口包 4. ...

  3. 天梯 L2 这是二叉搜索树吗?

    L2-004 这是二叉搜索树吗? (25 分) 一棵二叉搜索树可被递归地定义为具有下列性质的二叉树:对于任一结点, 其左子树中所有结点的键值小于该结点的键值: 其右子树中所有结点的键值大于等于该结点的 ...

  4. 快速掌握—HTML快速实现自定义Input开关

    HTML <input id="customSwitch" type="checkbox" /> <label for="custo ...

  5. 【转】常见Java面试题 – 第四部分:迭代(iteration)和递归(recursion)

    ImportNew注: 本文是ImportNew编译整理的Java面试题系列文章之一.你可以从这里查看全部的Java面试系列. Q.请写一段代码来计算给定文本内字符“A”的个数.分别用迭代和递归两种方 ...

  6. 详细解析Java虚拟机的栈帧结构

    欢迎关注微信公众号:万猫学社,每周一分享Java技术干货. 什么是栈帧? 正如大家所了解的,Java虚拟机的内存区域被划分为程序计数器.虚拟机栈.本地方法栈.堆和方法区.(什么?你还不知道,赶紧去看看 ...

  7. 键盘优雅弹出与ios光标乱飘解决方案

    前言 在移动开发中,会遇到这样的情况,比如说有一个输入框在最底部的时候,我们弹起输入框,输入框不会在输入键盘上. 说明白简单点就是,输入框被键盘挡住了.而且在原生中,输入框应该正好在输入键盘上,但是h ...

  8. Ubuntu 19.10 安装 jupyter

    安装pip3 ubuntu 19.10 已经没有python了,取代的是python3. 执行sudo apt install python3-pip安装pip3 安装jupyter 执行sudo p ...

  9. 从头学pytorch(二十):残差网络resnet

    残差网络ResNet resnet是何凯明大神在2015年提出的.并且获得了当年的ImageNet比赛的冠军. 残差网络具有里程碑的意义,为以后的网络设计提出了一个新的思路. googlenet的思路 ...

  10. springboot +fastdfs 上传文件到到云服务器

    fastdfs在云服务器的搭建和配置:https://blog.csdn.net/qq_41592652/article/details/104006289 springboot结构如下: appli ...