从读写分离到CQRS,张大胖是如何解决性能问题的?

  发布时间:2025-11-05 04:32:45   作者:玩站小弟   我要评论
1.不堪重负的数据库张大胖公司的数据库已经不堪重负了。这个系统最早是两个实习生写的, 按照最初的设计,只是内部用户玩的, 大家可以把一些闲置不用的东西放在上面做交换, 仅此而已,后来为了在互联网的大潮 。

1.不堪重负的从读数据库

张大胖公司的数据库已经不堪重负了。

这个系统最早是写分性两个实习生写的, 按照最初的胖何设计,只是解决内部用户玩的, 大家可以把一些闲置不用的问题东西放在上面做交换, 仅此而已,从读后来为了在互联网的写分性大潮中赚点钱,又包裹上了一层Web的胖何外衣, 让外界也可以访问。解决

大家没有想到互联网威力如此巨大,问题 用户量会如此之多,从读 他们系统使用的写分性Mysql数据库很快就撑不住了。

作为技术负责人的胖何张大胖早已经向老大申请了一笔费用, 专门买了一个高性能的解决服务器来应对, 但是问题汹涌而来的用户很快就把高性能给吃得连渣都不剩。

张大胖忧心忡忡: “老大,怎么办?

老大也是技术出身,反问道: “你分析过为什么数据库压力这么大吗? ”

“无非就是企商汇读写量太大了,尤其是有一些非常复杂的查询, 比如最近24小时最热门的物品之类,需要写很复杂的SQL, 运行起来实在太慢了。”

“我记得咱们俩聊过读写分离啊, 怎么不试一试?”

“老大啊, 你不知道,这实在是不好弄啊, 为了实现读写分离, 得把数据库拆分成master库和slave库, 还比较简单, 但是我们的系统代码也得改啊, 写数据的时候用master 库, 读数据的时候用slave库, 你知道我们这是上个世纪开发的系统,典型的遗留代码, 改动起来太麻烦了。”

老大说:“那也得改啊, 你要知道现在这个系统可是咱们公司***的收入来源了。源码下载 你们要是不想改,就退下来,我只好去找李小疯去做了”

张大胖向来瞧不起马屁精李小疯,技术不咋地,升的到挺快,一起进公司的, 现在已经比自己高一级了。

张大胖赶紧说:“ 别别, 还是我来”

张大胖带着几个弟兄和遗留代码奋战了几个月, 工作量不亚于一次重写。 张大胖深深地体会到,别看现有代码很烂, 但是经过无数人的修补,勉强能工作。 现在自己从头写一遍,出的问题更多,很多小细节考虑不到,被测出了无数Bug。

不过好处也是巨大的,这次重写,理清了业务, 实现了读写分离,还把缓存也用上了, ***熬了两天两夜,免费源码下载新系统终于上线了。

张大胖想着好日子就要开始了,崭新的代码, 崭新的系统,应该可以撑一段时间。

2.复杂的查询

可是新系统上线了一周后,问题又出现了,这次的问题主要集中在一些复杂的SQL查询上,这些SQL查询最要命的得有几十行! 严重地拖累了数据库 !

张大胖找来DBA 小梁过来做优化,小梁看了半天说: “没辙, 你们的业务太复杂了, 你看看有这么多表在做Join,怎么可能快呢?”

张大胖说:“这没办法啊,数据库就是这么设计的啊, 你懂的,无论如何也得满足***范式吧。 要不这样,你给我们创建一个视图(View) 吧, 把这个复杂的查询给封装起来, 这样我们使用起来就简单了”

“那也是换汤不换药啊, 实际的查询还在, 没有本质的改变, 照样还是慢。”

“唉,这可怎么办, 我们有20多个复杂查询,怎么才能提高速度呢?”

小梁说: “你看看这个超级复杂的查询, 不就是为了获得过去24小时的热门产品吗,要是有个表单独存放就好了 hot_products(id, name, desc, total_sold) , 这样以来一条简单的SQL就搞定”

小梁的话启发了张大胖: 实际上,一套单一的数据库表 对于报表、搜索、事务等不同的行为是不适当的 !

现在复杂的数据查询和简单的数据修改利用的就是同一套领域模型和数据库表, 现在的数据库表主要是为了新增、修改数据而设计的, 对于复杂的查询并不友好。 我们能不能单独的建一套数据库,专门应对查询呢?

有了这个专门的查询库, 用户在界面上发起查询的时候处理起来非常简单, 一条SQL就搞定,甚至都不用通过业务领域层,换句话说数据库模型和展示层是对应的! 再也不用像原来那样从原始数据库表中得到数据,转化成领域对象, 然后再转化成展示层对象, 实在是太麻烦了 !

但是这个专门的查询库该如何更新呢? 更重要的是能不能忍受数据的延迟呢?

3.CQRS

张大胖把自己的想法和苦恼给老大讲了下。

老大拍了拍他的肩膀: “看来你小子开窍了啊, 想得挺深入的, 从业务上看数据的延迟可以忍受,比如过去24小时的热门产品,一点点过时的数据对用户不会产生重大的影响。只要你能达到最终一致就可以了。”

“那我们该怎么更新这个专门的查询库呢?”

“我最近在看一个叫做CQRS的东西” 老大说 “ 你遇到的这个问题可以用同样的思路来解决下”

“什么是CQRS ? ”

"Command Query Responsibility Segregation,就是命令(增删改)和查询的责任分离, 你看看这个图"

“这和我刚才的图差不多啊” 张大胖说

“所以说思路是一致的嘛, 在CQRS中, 强调的是读(Query)和写(Command) 的分离 , 它背后的理念是用户读到的数据通常是过时的,比如过去24小时最火的产品, 既然如此, 为什么还要从数据库中读取一遍,转化为领域模型,DTO, VO, ***在UI层展示呢? 何不直接一点,干脆为‘读’专门建立一个直接的数据源呢? 这新的数据源不一定是关系数据库,可以是Cache ,可以直接存储为xml/json数据, 只要界面查询起来方便即可。 ”

“是,最早我也是这么想的,那这个Event是怎么回事?”

“Event 就是事件喽,例如有人下了一个订单, 导致某个产品已经卖出, 这个时候就可以发布一个产品已经卖出(ProductSold)的事件 , 其中包含产品的ID, 价格,卖出时间等属性, 这样的事件被处理以后,可以变成任意的Read Model,例如过去24小时最火的产品 。”

“奥,原来是这么玩的啊, 通过事件机制把同步变成异步 ” 张大胖说 “ 还有一个问题,如果我们用CQRS, 难道我们的应用需要把所有的Command 和Query完全分开吗, 查询都通过新的数据源? 可是很多查询很简单,直接使用关系数据库就够了啊。 ”

“不,不要把摊子铺得太大, 引入一种新的技术也是需要付出代价的,我们把同步操作变成了异步的操作, 得有良好的事件处理机制才可以。 所以先用这种思路把你的当前问题,也就是复杂查询的问题解决掉吧!” 老大***拍了板。

【本文为专栏作者“刘欣”的原创稿件,转载请通过作者微信公众号coderising获取授权】

戳这里,看该作者更多好文

  • Tag:

相关文章

  • 电脑进入PE出现错误的解决办法(排查PE进入错误的具体步骤和解决方案)

    摘要:电脑进入PEPreinstallationEnvironment,预安装环境)是一种用于系统恢复、修复和安装操作系统等工作的引导环境,但有时候在进入PE时会遇到一些错误。本文将介...
    2025-11-05
  • 对MySQL交换分区的实践

    【引自star_glm的博客】前言在介绍交换分区之前,我们先了解一下 mysql 分区。数据库的分区有两种:水平分区和垂直分区。而MySQL暂时不支持垂直分区,因此接下来说的都是水平分区。水平分区即:
    2025-11-05
  • 前端实现多文件编译器

    作者 |景遇一、概要在前端工程中,有时我们需要在浏览器编译并执行一些代码,这种需求常见于低代码场景中。例如我们在搭建时需自定义一部分代码,这些代码需要在渲染时执行。为了方便起见,我们写的代码一定是
    2025-11-05
  • 这个 Linux 图形计算器让数学很有趣

    就像你在高中时最喜欢的图形计算器一样,KAlgebra 是科学计算器的同时还有 2D 绘图仪等功能。如果你在高中时期一直盯着 TI-80 系列计算器,但后来就在也没动过它,那么你有时可能会渴望重温那些
    2025-11-05
  • 解决电脑关键事件错误的有效方法(保护您的电脑免受关键事件错误的影响)

    摘要:在数字化时代,电脑已经成为人们生活和工作中不可或缺的工具。然而,我们常常会遇到一些关键事件错误,如系统崩溃、病毒感染、软件冲突等,这些错误给我们的使用带来了不便和困扰。为了保护您的...
    2025-11-05
  • MySQL Schema与数据类型的优化

    选择优化的数据类型:1、 更小的通常更好:一般情况下,应该尽量使用可以正确存储数据的最小数据类型。更小的数据类型通常更快,因为他们占用更少的磁盘,内存和cpu缓存,并且处理时需要的cpu周期也更少。2
    2025-11-05

最新评论