前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >一周技术学习笔记(第62期)-CQRS是”有点不同“的读写分离

一周技术学习笔记(第62期)-CQRS是”有点不同“的读写分离

作者头像
王新栋
发布2022-06-15 17:31:20
3080
发布2022-06-15 17:31:20
举报
文章被收录于专栏:程序架道程序架道

对数据的操作一共就四种。

图自https://time.geekbang.org/dailylesson/detail/100056986

我们把这四种操作,又划分为两类,读和写

为了提升对数据库的性能,我们又做了读写分离。

上面这个图是我们最为熟悉的读写分离场景了,另外我们也熟悉了这样的方法有两个不好地方。

1、写库有单点故障问题。

2、数据库同步有延迟。

TIP:读写分离,更主要是为了减少读操作的压力。

有了数据库层面的”归纳“:CRUD->读、写,那么在应用层面我们可以做点啥呢。

可以继续”归纳“:CRUD->读、写->查询、命令。

这里将查询和命令分开,也就是我们要说的CQRS(Command Query Responsibility Segregation)模型,命令与查询职责分离

图自https://time.geekbang.org/dailylesson/detail/100056986

这样,我们在应用层面就可以抽象成如下模样。

图自https://time.geekbang.org/dailylesson/detail/100056986

到这里,估计你看出来了,没错,CQRS是”有点不同“的读写分离

下面,我们主要说下”有点不同“。

当我们说传统的读写分离的时候,锚点侧重在数据库层面,当我们说CQRS的时候,锚点侧重在应用层面。

在应用层面,我们一直需要考虑的一个问题是如何正确的划分操作的边界和职责,这里说的操作也可指服务操作,你可以联想微服务中的环境。

将操作的职责划分清楚,有一个基本的设计原则,单一职责,你也可以理解CQRS的核心设计基础来自单一职责。

将操作的职责划分清楚,还有一个可以借鉴的设计原则,比单一职责粒度稍微粗一些,就是我们常说的分离关注点,你也可以理解CQRS是分离关注点设计原则的应用场景之一。

CQRS 把数据的变更和查询拆开了,各有各的数据模型。

TIP:写存储可以用MySQL这样的关系型数据库,而查询存储则可以使用Elasticsearch作为存储。命令-查询职责分离(CQRS)模式是一种应用于这种场景的通用模型,它显式地将系统中的读(查询)和写(命令)进行分离。

静态上,拆分了这两块的代码,使各自可以采用不同的技术栈,做针对性的调优。命令模型负责数据的变更,并把最新数据同步给查询模型(有时候类似数据异构)。

动态上,切分了流量,能够更灵活的做资源分配,处理数据逻辑的时候,查询模型根据自己的想法来安排数据,想怎么用就怎么用

好处是可以让查询更加自由,放飞自我,更快的满足多变的业务需求。坏处是增加了架构的复杂度,有时候可能需要维护很多个查询模型,另外还有数据同步带来的问题。

我们上面提到了数据异构。

那么体现数据异构的地方在哪里呢,可以看一看下面这幅图。

在这里,事件处理器消费这些事件,以便构建合适的查询模型。具体的实现方式当然可以使用RabbitMQ或者Kafka这样的中间件。

比如,在线投资交易平台系统中,有customer服务、order服务、fee服务,现在要汇总所有账户的订单手续费,并且要按照不同的属性,订单类型、资产类别、支付方式,来进行分类汇总。仅仅在单个服务层面是不可能完成这个功能的,因为不管是customer服务、order服务还是fee服务,它们都不拥有全量的数据来支持按照那些属性过滤,每个服务只有一部分数据

这个时候采用CQRS的设计方法,我们就可以构建出一个CustomerOrder的查询服来组装上面那个查询诉求。

查询服务通过其他服务发出的事件消息来组建复合型的数据视图。

既然谈到了事件,也许此时此刻你可能联想到了DDD中的事件溯源模式,因为它们确实有点哪儿相似或者哪儿有点关联。

事件溯源机制有两个核心的问题:

1、如何生成领域事件?

2、生成领域事件后,如何获取领域对象的状态信息?

上面关于事件的两张图里面已经可以”窥一斑“了。多少是回答了这两个问题的,有事件发射器和接收器,也有状态对象的获取。实际上CQRS模式可以和事件溯源模式天然的进行整合。

图自网络

最后,引用《微服务实战》这本书的一段话,结尾。

想要全面理解CQRS是比较困难的,它需要大家采用一种不同于之前处理常规的CRUD API时的思维方式。但是,在微服务应用中,CQRS确实很有用的。如果应用得当,CQRS有助于确保查询功能的性能和可用性,即便数据和功能是隶属于不同服务的不同数据存储上的。

另外下面是关于微服务相关的一些知识点,来自《微服务实战》这本书。

(1)在跨服务的交互中实现ACID特性是很困难的,微服务需要采用不同的方式来实现一致性。

(2)类似两阶段提交这样的协调方案会引入加锁操作,扩展性不好。

(3)基于事件的架构可以解除各个独立组件之间的耦合,并为微服务应用的业务逻辑和查询的可扩展性打下基础。

(4)倾向于高可用,而非一致性,这会使得架构的可扩展性更强。

(5)Saga是由一组消息驱动的、独立的本地事务组成的全局操作。它们通过补偿操作来回滚错误的状态,以实现一致性。

(6)在构建反映现实世界环境的微服务时,预见失败场景并做好准备是非常重要的一部分内容,操作的隔离性反而没那么至关重要。

(7)我们通常通过组合多个API的结果来实现跨多个微服务的查询功能。

(8)高效的复合型查询应该采用CQRS模式来实现一套独立的读数据模型,特别是在那些查询模式需要采用另一种数据存储系统时。

提问1,如果的业务是涉及金融交易的部分,需要保证主从数据库的强一致性,但是MySQL复制又不能保证强一致性,这样的情况下该怎么办呢。

业务层上只有2\3PC提交协议,数据层上只有Paxos算法。

学习参考资料(文中配图来自此处):

https://time.geekbang.org/column/article/7045

https://time.geekbang.org/dailylesson/detail/100056986

《微服务实战》

----END----

这里记录,我每周碰到的,或想到的,引起触动,或感动的,事物的思考及笔记。不见得都对,但开始思考记录总是好的。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2022-05-01,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 程序架道 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
数据库
云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档