美团、快手、去哪儿网是如何构建测试环境的?点击查看实践案例>> 了解详情
写点什么

对 CQRS 的一次批判性思考

  • 2015 年 7 月 23 日
  • 本文字数:1498 字

    阅读完需:约 5 分钟

在今年的 NDC 大会上, Udi Dahan 进行了一场有关 CQRS 的演讲。他在演讲中提到,如果从更广义的架构角度来看,除了命令与查询职责分离(CQRS)之外,还有其它类似的架构风格可以选择,例如事件驱动架构(EDA)与发布- 订阅架构。而在某些场景中,使用传统的数据库技术也能够解决同样的问题,并且要简便的多。Udi Dahan 的想法是应当多考虑一些应用CQRS 的不同方式。而在确实需要CQRS 架构的场合,他认为也存在着一种可替代的方式能够实现CQRS 的大部分目标,同时与传统的CQRS 相比其可变部分更少。

Dahan 与 Greg Young 都可称得上是位于 CQRS 架构最前沿的专家,在他与客户进行交流的过程中,他总是察觉到一点,即可伸缩性是应用 CQRS 架构的主要理由之一。在进行大量的读操作时,如果将读取与写入操作进行分离,将能够提高查询的可伸缩能力。但 Dahan 也提示道,现在已经可以通过某些技术实现读写分离,并且只需极小的代码改动,甚至是零改动,他认为开发者们应当注意到这种技术的存在。另一方面,Dahan 认为,由于应用 CQRS 这一主题已经在全球范围内进行了多次演讲,在社区中无意中形成了一种“必须”使用 CQRS 的压力,这也是人们应用 CQRS 架构的原因之一。

其实对于读取密集型应用环境来说,可以通过另一种途径实现可伸缩性,即主/ 从复制。数据的修改全部发生在主节点上,数据将同步到一个或多个进行读取的从节点上。这种方式已经存在很久了,并且在许多数据库机制中都已经得到了完整的支持。但Dahan 也将它定义为一种CQRS 架构,因为它确实做到了读写分离。他也提到,如果在生成查询结果时需要进行复杂的连接操作,那么这种数据复制机制无法解决由此引起的延迟问题,但至少这种机制能够通过加入更多的从节点克服数据吞吐量方面的问题。

Dahan 还推荐了一种用于处理可伸缩性问题的解决方案,即数据分片、或数据库分区。这种方式将某张表中的数据切分到数据库的多个实例中,并通过某个字段在实例之间进行分布,例如客户的名称。这种方式的一大优点在于能够设置多个主节点,因此可以对命令与查询两方面同时进行扩展。而许多数据库技术本身就支持分区能力,只需一些非常简单的代码就可以实现。Dahan 同时提到,在使用多个主节点的情况下无法支持跨记录的事务,因此就像对解决方案领域所进行的分区一样,对业务领域也要进行某种程度的划分。

Dahan 认为在某一种场景下是非常适合应用 CQRS 架构的,即具有高竞争性的业务领域。在这种领域中的负载非常大,而且具有高度的局域性。一旦出现并发异常就可能导致大多数事务操作开始失败、无法释放数据库连接、阻塞用户请求等一系列问题,产生巨大的系统瓶颈。这种测试用例在进行性能测试时经常会被忽略,一般在进行可伸缩性测试时,通常会针对多条记录创建大量的用户请求,而不是让所有的请求都集中于少数几条记录上。即使完美地实现了CQRS 架构,这种瓶颈依然会出现在数据查询的场景,由于后台的进程不能快速地完成更新操作,导致查询模型总是无法及时获得最新的数据。

对于这种高竞争性的问题,Dahan 的解决方案是转为使用一种基于事件的模型,其数据模型是非阻塞式的、并且是只增的(append only),这就意味着该模型不会受到竞争性的影响。但这种方案可能会带来一个问题,因为它影响了某些业务规则。打个比方,某条业务规则规定只有在订单中的产品都有足够的库存时才允许接受订单。而这种方案则要求在业务处理上提供更高的灵活性,甚至可能会对需求产生变更。拿这个订单的例子来说,业务流程应当允许在不检查库存的情况下直接接受这个订单。而如果在处理订单时发现其中有某些产品库存不足,需要由业务人员决定如何处理这种情况。

查看英文原文: A Critical Look at CQRS

2015 年 7 月 23 日 10:134298
用户头像

发布了 428 篇内容, 共 161.8 次阅读, 收获喜欢 32 次。

关注

评论

发布
暂无评论
发现更多内容

Node.js 日志之 winston 实践

devpoint

nodejs 10月日更 winston logger

粪菌移植的背后,肠道菌那些你不知道的事儿

脑极体

【LeetCode】Fizz Buzz Java题解

Albert

算法 LeetCode 10月日更

趣说Node.js的回调函数

Regan Yue

node.js JavaScrip 10月日更 Regan Yue

拿蚂蚁offer,全靠阿里P8大牛总结的Java架构开发手册

Java 编程 程序员 架构 面试

面试作弊神器?!阿里P8亲自撰写的这份Java最新面试手册

Java 程序员 架构 面试 后端

SpringBoot 实战:在 RequestBody 中优雅的使用枚举参数(原理篇)

看山

Java Spring Boot 10月日更 Effective Spring

”微博评论“的高性能高可用计算架构

缘分呐

架构设计实战

双非学历为进大厂天天刷Java面试题,面试却履败,原因竟是算法?

Java 编程 程序员 架构 IT

隐蔽的角落-这次我们只聊Cilium IPAM

Lance

《第1章 预备知识》

IT蜗壳-Tango

10月日更

linux中vi,vim操作技巧

入门小站

Linux

业界良心啊!第五次更新的Spring Cloud Alibaba升级太多内容

Java 编程 程序员 IT 计算机

SSRF漏洞实例分析

网络安全学海

网络安全 信息安全 渗透测试 WEB安全 漏洞分析

存量时代会员深度运营逻辑

boshi

深度思考 运营

Prometheus 基础查询(一)

耳东@Erdong

Prometheus 10月日更

CSS架构之Components层

Augus

CSS 10月日更

【Flutter 专题】30 图解自定义底部状态栏 ACEBottomNavigationBar (二)

阿策小和尚

Flutter 小菜 0 基础学习 Flutter Android 小菜鸟 10月日更

「架构师教程」二十年架构师「马士兵」大牛的Java高级架构师教程

Java 编程 程序员 IT 计算机

【Vuex 源码学习】第十二篇 - Vuex 插件机制的实现

Brave

源码 vuex 10月日更

Leetcode 题目解析:279. 完全平方数

程序员架构进阶

算法 LeetCode 动态规划 10月日更

在线下划线转驼峰,驼峰转下划线工具

入门小站

工具

IM系统消息丢失问题排查反思

轻口味

IM Android; 10月日更

015云原生之大数据技术

穿过生命散发芬芳

云原生 10月日更

gRPC,爆赞

AlwaysBeta

golang 编程 gRPC 后端 Go 语言

并发相关的性质学习笔记

六维

并发 10月日更

Facebook宕机事故,暴露了上云不是唯一的答案

脑极体

python 数据库编程,这篇是针对 mysql 的,滚雪球学Python第4季第13篇

梦想橡皮擦

10月日更

keytool生成keystore、truststore、证书

黄敏

实践篇 -- Redis客户端缓存在SpringBoot应用的探究

binecy

缓存 springboot redis sentinel

阿里架构师总结Go语言和java语言之间的对比联系

hanaper

对CQRS的一次批判性思考_架构_Jan Stenberg_InfoQ精选文章