DDD-CQRS的落地案例

摘要

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

问题分析

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

以前业务中无法使用CQRS,在于使用CQRS后,数据的维护变得异常麻烦。好比我对一个表单进行了反复修改,生成了N份历史修改数据,获取最新数据时须要对这些历史数据进行合并,变得异常麻烦。
此次业务可以使用在于,架构

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

具体设计

系统总体采用CQRS+Event-Sourcing来实现框架

CQRS微服务

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

文本编辑这块领域模型很薄,没有什么领域校验与约束,按读取数据/更新数据分离,当读写压力不一样时,之后能够拆分红不一样的服务,分别扩展。.net

Event Sourcing(事件溯源)设计

a.不保存对象的最新状态,而是保存对象产生的全部事件
b.经过事件溯源(Event Sourcing,ES)获得对象最新状态;3d

系统总体分为三大部分对象

一. 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能解什么问题

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

相关文章
相关标签/搜索