美文网首页
24.CQRS:一种有界上下文的架构

24.CQRS:一种有界上下文的架构

作者: 鸿雁长飞光不度 | 来源:发表于2022-08-29 08:58 被阅读0次

    1.单个模型处理两个有界上下文的面临的挑战

    DDD强调使用聚合保持多个实体的数据一致性、处理并发、强制执行领域的不变条件,但是一个应用程序的报告需求(数据展示)可能和聚合的结构不一致(在存储库的末尾也提到过这个场景,https://www.jianshu.com/p/287555b75e38)此时面临的问题如下。

    1. 为了支持生成用于展示数据,聚合会遭到破坏。
    • 聚合需要公开内部状态,破坏了封装性。
    • 聚合增加与UI展示相关的属性,这些属性与领域不变条件不大(聚合是领域的抽象而不是依赖UI,聚合要围绕领域行为设计)。
    1. 读取往往比写入多很多,造成性能低下。

      UI需要多个聚合的极个别属性,但是聚合都是一次加载所有的内容的,会导致性能低下。

    image.png

    2. CQRS:复杂有界上下文的一种更好架构

    CQRS(命令与查询职责分离),通过为读取和写入提供两个不同的模型分别处理业务请求。


    image.png

    2.1 命令端

    image.png

    命令端关注的是领域的规则,代表了满足领域任务的领域逻辑,但是不支持查询,返回结果是任务执行成功的确认。

    一个命令就是一个业务任务,处于应用层内部,应该以业务语言编写(是捕获系统行为而非领域模型的术语和概念的语言),这里不是UL。

    image.png

    命令需要揭示业务意图,上面的例子表示明确表示用户需要兑换礼品券,应该是用动词,在领域事件里面用的是完成时。

    image.png

    命令端的领域模型是为了实现领域规则和逻辑,不需要有不必要的展现属性,聚合支持命令处理而非对现实环境建模,有利于专注行为和不变条件,保持聚合在较小的规模。

    2.2 查询端

    查询端的架构关注的是领域上的报告,查询的返回对象就是为了UI上展示的数据所定制的DTO,不需要领域模型,数据可以直接从数据库读取出来,利用ORM可以直接很简单的映射,如果一些属性在数据库没有预先写入,可以通过DTO里面的方法进行计算获取或者使用领域服务。

    可以采用不同的数据结构进一步实现读取和写入分离,写入操作引发领域事件,由程序处理更新读取的数据结构的内容(这个主要是为了提高读性能)。

    image.png

    3.CQRS误解

    3.1CQRS是最终一致性的

    最终一致性是异步的更新读取模型的实现方式,比如上面说的通过领域事件更新,但是这个先决条件,它主要解决的还是提高读性能让读取端变的可扩展。CQRS目前主要解决读取和事务问题不一直带来的复杂性,可以使用相同的数据和事务更新读取模型结构。(如果大量使用了缓存系统会变成最终一致性)

    3.2 需要事件溯源

    事件溯源是同时构建读取和写入模型的方法,但不是必须的,主要目标确保审计追踪准确。

    3.3 命令是异步的

    看场景,高度协作的领域会有多个用户对相同数据进行变更,使用异步命令是合理的,确保命令依次处理,简单的场景没有必要。

    3.4 需要采用消息

    系统按照最终一致性设计或者异步任务时需要消息,否则会增加不必要的复杂性。

    4.可以扩展的应用程序模式

    4.1扩展读取端:最终一致的读取模型

    image.png

    提高读性能,消费更新数据的消息转换成读取需要的格式。

    多个有界上下文的数据合并

    image.png

    消费领域事件

    image.png

    消费数据库的binlog

    4.2 扩展写入端:使用异步命令

    image.png

    异步处理的任务要能够将状态反馈给客户端,否则会困惑。

    4.3 同时进行扩展写入和读取

    image.png

    写入端通过消息异步处理数据更新写入模型,写入模型处理完成后发布消息更新读取模型。

    相关文章

      网友评论

          本文标题:24.CQRS:一种有界上下文的架构

          本文链接:https://www.haomeiwen.com/subject/gbjhnrtx.html