1。不堪重负的数据库张大发所在公司的数据库已经不堪重负。这个系统最初是由两个实习生编写的。按照最初的设计,它只供内部用户玩。大家可以放一些闲置的东西在上面兑换。就这样。后来为了在互联网大潮中赚点钱,又裹了一层Web外衣,让外界也可以访问。所有人都没有想到,互联网的力量会这么大,用户量会这么大,以至于他们系统使用的Mysql数据库很快就支持不住了。作为技术负责人,张胖子已经向老板申请了费用,买了一台高性能的服务器来应对。然而,用户的涌入很快就吞噬了高性能。张大胖着急道:“老大,我们怎么办?”老大也是技术出身,问:“你分析过为什么数据库压力这么大吗?”比如最近24小时最火的一条,需要写很复杂的SQL,跑起来太慢。试试看?”“老大,你我不知道,真的很难做。为了实现读写分离,数据库不得不拆分成主库和从库。比较简单,但是我们的系统代码也需要改一下。写数据的时候我们用主库,读数据的时候用从库,要知道这是上个世纪开发的系统,典型的遗留代码,改起来太麻烦了。”老大说:“那必须要改,你要知道现在的体制不是我们公司唯一的收入来源。如果你不想改变它,你可以退出。只好找李晓峰来做。”张大胖一直看不起李霄峰这个马屁精。一起进公司的现在比我高一级。张胖子忙道:“你别动手,我来。”张胖子带着几个兄弟,跟遗留代码打了几个月,工作量不亚于重写。张胖子深深地明白,现有的代码虽然不好,但是经过无数人的鼓捣也勉强能用。现在是从头开始写,问题比较多,很多小细节考虑不周,测试了无数bug。但是,好处也是巨大的。这次rewrite明确了业务,实现了读写分离,同时也使用了缓存。经过两天两夜的***,新系统终于上线了。张胖子心想,好日子要开始了,新代码、新制度应该还能维持一段时间。2.复杂的查询但是在新系统上线一周后,问题又出现了。这次的问题主要集中在一些复杂的SQL查询上。这些SQL查询必须有几十行!严重拖垮了数据库!张胖子叫来DBA小梁做优化。萧亮看了半天,道:“不行,你的业务太复杂了,你看这么多表做Join,怎么可能快?”张胖子说:“没办法,数据库就是这么设计的,你懂的,无论如何都要满足***范式。不然的话,你可以给我们创建一个视图(View)来封装这个复杂的查询,这样,我们可以很容易地使用它。”“那只是换汤不换药,实际查询还在,没有本质的改变,还是慢。”“哦,怎么办,我们有20多个复杂的查询,怎么提高速度呢?”小亮说:“你看这个超级复杂的查询,不就是为了获取过去24小时内的热卖商品吗,要是有一个单独的表hot_products(id,name,desc,total_sold)就好了,这样一个简单的SQL就可以处理它。”肖亮的话启发了张大胖:其实单一的一套数据库表对于报表、搜索、交易等不同的行为是不合适的!现在复杂的数据查询都是用同一套领域模型和数据库表进行简单的数据修改。现在的数据库表主要是为了增加和修改数据而设计的,对复杂的查询并不友好,能不能建一个单独的数据库来处理查询呢?有了这个专门的查询库,用户在上面发起查询,处理起来就非常简单了接口,一条SQL连业务领域层都不走就可以搞定,也就是说数据库模型和展示层一一对应!从原始数据库表中取出数据,转成领域对象,太麻烦了然后转换成显示层对象!但是这个特殊的查询库怎么更新呢? 更重要的是,你能承受数据的延迟吗?3.CQRS张大发跟老板说他的想法和烦恼。老板拍了拍他的肩膀:“看来你是开明了,你想得很深了。从业务的角度来说,数据的延迟是可以容忍的。比如过去24小时的热门产品,有一点点过时的数据不会对用户产生重大影响。只要能达到最终一致性就好了。”“那我们应该怎么更新这个特殊的查询库呢?”“我最近在看一个叫CQRS的东西,”老板说,“你遇到的问题用同样的思路就可以解决。”“什么是CQRS?”“CommandQueryResponsibilitySegregation是命令(增删改查)和查询职责的分离。看这张图。”强调的是读(Query)和写(Command)的分离。其背后的想法是,用户读取的数据通常是过时的,比如过去24小时内最流行的产品。既然如此,为什么从数据库读取一次,转化为领域模型,DTO,VO,***显示在UI层呢?为什么不更直接一点,直接创建一个直接的数据源来‘读取’呢?这个新数据源不一定非得是关系型数据库,可以是Cache,可以直接存储为xml/json数据,只要接口方便查询即可。”“是的,我一开始也是这么想的,所以这个事件是怎么回事?”“活动就是活动,比如有人下单,某件商品已经售出,这时候你就可以发布一个已经售出的商品。”ProductSold事件中包含了产品ID、价格、销售时间等属性,这样的事件经过处理后,可以成为任意ReadModel,比如过去24小时内最热的产品。“哦,原来是这么玩的,利用事件机制把同步变成异步”张大发说,“还有一个问题,如果我们使用CQRS,我们的应用中是否需要将所有的Commands和Query完全分离?全部通过新的数据源查询?但是很多查询很简单,直接用关系型数据库就够了。”“不行,不要传播太多。引入新技术是要付出代价的。我们把同步操作变成了异步操作,我们必须要有一个很好的事件处理机制。所以先用这种思路解决你现在的问题,也就是复杂查询的问题!”老板***做出了决定。【本文为专栏作家“刘欣”原创稿件,转载请转载通过作者微信公众号编码获取授权】点此阅读作者更多好文
