在互联网项目中,当业务规模越来越大,数据也越来越多,随之而来的就是数据库压力会越来越大。
这里再分享几个针对数据库优化的常规手段:数据读写分离与数据库 Sharding。这两点基本上是大中型互联网项目中应用的非常普遍的方案了。
从读写分离到 CQRS
由于互联网业务场景,大多数是读多写少,因此进行数据库的读写分离是一件非常简单且有效率的方案。
读写分离简单点来说就是把对数据的读操作和写操作进行分开来,让这两种操作去访问不同的数据库,这样的话,就可以减轻数据库的压力了。
常规的有 2 种方式:
1、使用编码方式
这个方式主要是靠开发同学在编码的时候,根据读写不同的操作需求,去调用不同的数据源。
但是这种方式有点硬编码的味道了,而且对开发同学而言还得额外关注这个事情,多了一个编码成本且容易不小心忽略掉。
2、使用中间件
这种方式就是在后端数据库的前面,前置一个 数据库代理服务,如下图的:MySQL-Proxy 是 Mysql 提供的一个中间件,用于实现读写分离请求,但这个组件实际用的人不多,我们可以选择其它的一些开源的组件替代,例如:Mycat、ProxySQL 等等,但大致的原理比较类似,通过这个图很容易理解这个模式。
3、CQRS:Command Query Responsibility Segregation
命令(增删改)和查询的责任分离
通过上图可以简单的理解一下 CQRS。CQRS 重点强调的就是 Query(读) 和 Command(写)的分离,在业务上将职责分离清晰,Command 主要做业务逻辑的执行,Query 来负责数据查询和展示。同时 这两种操作是基于不同的数据源,甚至是一个是数据库,另外一个是 NoSQL 都可以,Query 去查询的数据源可以直接按照领域模型进行存储,而并不是按照数据模型去存储,这样查询出来就立即可以展示,而不用转换,且查询效率高。
其实 CQRS 是由鼎鼎大名的 Martin Fowler 提出,搞计算机的应该都认识。想要更深入的去学习 CQRS,可以翻看 Martin Fowler 公开的资料。
Sharding(分库分表)
随着数据库里的数据越来越大,单表查询的性能已经不能满足业务要求了,这个时候就需要进行分表处理了,将大表拆分为若干个小表,不同的分表中数据也不一样,这样可以分散查询压力,提高处理效率。
然而,当表越来越多,所有的数据都在一个数据库上时,网络 IO 以及文件 IO 也都会集中在一个数据库上,可能会超过单台服务器的容量, CPU、内存、文件 IO、网络 IO 都会成为系统的瓶颈,QPS/TPS 也会超过单数据库实例的处理极限。那么这个时候就需要对数据库进行分片处理。
因为分表和分库的思路类似,因此下面统一来聊技术方案。其实分库分表只是我们通俗的便于理解的说话,正确的描述应该是:数据分片
数据的分片主要有 2 种模式:
• 垂直拆分
• 水平拆分
两种拆分应用的场景是不同的:
垂直拆分,是指按照业务模块进行拆分。简单来讲,就是把业务紧密的模块的字段 / 表放在一起,放在同一个数据库或者服务器上。将不同业务的字段 / 表进行独立,拆到不同的数据库或者服务器上。
水平拆分,是指纯粹的按照某种数据规则 / 格式进行拆分。水平拆分需要注意的是,随着数据动态的变化,分片数量可能需要随之动态调整,另外就是水平分片是没有考虑业务特征的,因此在进行业务汇总查询或者分片中事物处理的时候就比较麻烦一些。
另外,在实际应用中,两种拆分模式一般会结合在一起使用,效果更佳。