💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
# 读写分离 当一个公司业务不断扩展,用户量大量增加,原来使用的数据库很可能就撑不住了。那么可以 - Scale-in,扩充硬件的性能,但是很可能用户量继续增长,增加的性能很快就吃光了。 - 读写分离:数据库撑不住了,无非就是读写量过大,特别是有一些复杂的查询比如最近24小时最热门的产品等。需要很复杂的SQL语句,运行起来当然是慢。 但是为了读写分离,需要把数据库拆分为master库和Slave库, 市面上主要的关系数据库都支持**数据复制功能**,所以可以把一个数据库拆分为Master和Slave两种角色,**写操作**在主上,由Master服务器向其他Slave服务器进行同步。 而**读操作**以及数据分析等离线操作都在Slave服务器上进行。 我们知道互联网的很多应用都是读的,这样有多个Slave可以**负载分担**一下,又可以保证数据的可用性和正确性。 ![image.png](http://upload-images.jianshu.io/upload_images/1323506-7371a2116b037768.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 但是相应的原有的**应用代码**也需要修改,必须改为写数据用master库,读数据的时候使用slave库,就相当于重写了。 # 复杂查询 但是就算重写了代码,发现性能还是无法得到明显的提升,原因仍然是使用了太多复杂的查询,比如说有很多表在联接,在[数据库(四),数据库组成部分](http://www.cnblogs.com/dy2903/p/8438206.html)里面我们都说过,联接非常消耗性能。 那么我们可不可以**单独用一张表**来存放过去24小时的热门产品啊,这样只需要使用简单的SQL就能搞定。 也就是说,一套单一的数据库表对报表、搜索、事务等不同的行为是不适当的。 现在的表是为了**新增、修改数据**而设计的,对复杂查询不适合。 但是我们还需要考虑这个查询库如何更新的问题,还就是可能不是实时更新,我们能否忍受这种延迟的问题。 # CQRS 能否忍受延迟的问题需要从业务上来看,比如过去24小时热门的极品,一点点过时的信息没有太大的影响,只要求最终一致即可。 我们可以使用CQRS(Command Query Responsibility Segregation),也就是增删改的**命令与查询责任分离**。 ![image.png](http://upload-images.jianshu.io/upload_images/1323506-f7e4c298714c8f06.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 在CQRS中,强调的是读(Query)写(Command)分离,因为用户读到的数据通常是过时的,那么为什么还需要从数据库读一遍呢,可以直接建立一个读数据源。可以是Cache,可以是XML、JSON等。 那之前提到的怎么**更新**的问题怎么解决?可以使用Event,也就是事件,比如某个产品卖出去了,可以发布一个事件,修改原有的Read Model。 这样就通过事件机制把同步变成了异步。 最后,这种方法最好只在**复杂查询**中用,原来的简单查询依然在关系型数据库里面取。为什么呢?因为引入一种新的技术需要付出代价,比如同步变异步了,还需要事件机制,我们不能只看到新技术的优点,而看不到缺点了。 ![image.png](http://upload-images.jianshu.io/upload_images/1323506-c9226a8db16cfc9b.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) # 主要参考 [从读写分离到CQRS,张大胖是如何解决性能问题的?](http://mp.weixin.qq.com/s?__biz=MzAxOTc0NzExNg==&mid=2665513844&idx=1&sn=82a70f987fdf56a47debffc995addfec&chksm=80d67b37b7a1f221187a97af92ec7fed5b31d1fae3831d7b59b28c34935afb7765cb1b7a4fb0&scene=21#wechat_redirect)