面试官:聊聊你们项目中怎么做的分库分表吧(上)

想必各位小伙伴在面试大厂的时候都遇到过这个面试题,要是提前有准备还好,没准备的话可能就被打了个措手不及,本文将从为什么使用分库分表技术分库分表的基本概念分库分表的好处以及分库分表的注意事项来聊一聊这个话题。

数据库架构演变

刚开始我们只用单机数据库就够了,随后面对越来越多的请求,我们将数据库的写操作和读操作进行分离, 使用主库(Master)负责写,使用多个从库副本(Slaver Replication)负责读,从库从主库同步更新数据,保持数据一致。架构上就是数据库主从同步。从库可以水平扩展,所以更多的读请求不成问题。

但是当用户量级上来后,写请求越来越多,该怎么办?加一个Master是不能解决问题的, 因为数据要保存一致性,写操作需要2个master之间同步,相当于是重复了,而且更加复杂。

这时就需要用到分库分表(sharding),对写操作进行切分。

为什么要使用分库分表

在业务系统中关系型数据库(以MySQL为例)本身比较容易成为系统的瓶颈,比如单机存储容量、连接数、处理能力有限等等的原因非常容易让我们的系统变得“迟缓”,甚至崩溃。即使我们的数据库架构采用主从模式也依然存在这个问题,随着系统越来越复杂,不可能去用多主多从的模式,而且多主多从模式中数据一致性的问题处理起来比较棘手,所以也依然存在很多查询不理想的情况。总的来说,分库分表是为了解决数据库存储大量数据时出现的性能瓶颈。

  • IO瓶颈

关系型数据库IO瓶颈,热点数据太多,数据库缓存放不下,每次查询时会产生大量的IO,从而导致查询效率降低;网络IO瓶颈,请求的数据太多,网络带宽不够,导致查询效率降低。

  • CPU瓶颈

比如我们的SQL中包含join,group by,order by等非索引字段条件查询等,会增加CPU运算的操作带来的消耗;单表数据量太大,查询时扫描的行太多,SQL效率低,CPU率先出现瓶颈。

分库分表的基本概念

分库分表的方式有垂直切分水平切分两种,通常推荐垂直切分,因为更符合我们日常处理问题的方式。

  • 垂直分库
    面试官:聊聊你们项目中怎么做的分库分表吧(上)

以表为依据,按照业务归属不同,将不同的表拆分到不同的库中。每个库的结构都不一样,每个库的表结构也不一样,并且没有交集,最后将不同的库部署在不同的服务器上。数据库业务层面的拆分,和服务的“治理”,“降级”机制类似,也能对不同业务的数据分别的进行管理,维护,监控,扩展等。 数据库往往最容易成为应用系统的瓶颈,而数据库本身属于“有状态”的,相对于Web和应用服务器来讲,是比较难实现“横向扩展”的。 数据库的连接资源比较宝贵且单机处理能力也有限,在高并发场景下,垂直分库一定程度上能够突破IO、连接数及单机硬件资源的瓶颈。

  • 垂直分表
    面试官:聊聊你们项目中怎么做的分库分表吧(上)

以字段为依据,按照字段的活跃性,将表中字段拆到不同的表(主表和扩展表)中。一般是将热点数据作为主表,这样更多的热点数据就能被缓存下来,进而减少了随机读IO。将不常用的, 数据较大,长度较长(比如text类型字段)的拆分到“扩展表“。但是查询的时候不要去join表,因为join会增加CPU的负担,而且join必须两个表在同一台实例上。正确的做法是:分别获取主表和扩展表数据然后用关联字段关联得到全部数据。

  • 水平分库

面试官:聊聊你们项目中怎么做的分库分表吧(上)
以字段为依据,按照一定策略(RANGE、HASH取模等),将一个库中的数据拆分到多个库中。每个库的结构都一样;每个库的数据都不一样,没有交集;所有库的并集是全量数据。一般水平分库后,多个数据库是部署到不同服务器上,这样能够有效的缓解单机和单库的性能瓶颈和压力,突破IO、连接数、硬件资源等的瓶颈。

  • 水平分表

面试官:聊聊你们项目中怎么做的分库分表吧(上)
针对数据量巨大的单张表(比如订单表),按照某种规则(RANGE、HASH取模等),切分到多张表里面去。 但是这些表还是在同一个库中,所以数据库操作还是有IO瓶颈,不建议采用。

分库分表的好处

当然任何解决方案方案都是有利有弊,我们应该尽量发挥它的优势,但是也不能够忽略它的劣势。

分库分表存在的问题