引言 微服务、面试分布式大行其道的总被知识当下,中、问分高级Java工程师面试题中高并发、库分大数据量、表办分库分表等已经成了面试的点懂高频词汇,这些知识不了解面试通过率不会太高。面试 你可以不会用,总被知识但你不能不知道,问分就是库分这么一种现状。技术名词大多晦涩难懂,表办不要死记硬背理解最重要,点懂当你捅破那层窗户纸,面试发现其实它也就那么回事。总被知识 一、问分为什么要分库分表 关系型数据库以MySQL为例,单机的存储能力、连接数是有限的,它自身就很容易会成为系统的瓶颈。当单表数据量在百万以里时,我们还可以通过添加从库、优化索引提升性能。 一旦数据量朝着千万以上趋势增长,再怎么优化数据库,很多操作性能仍下降严重。为了减少数据库的负担,服务器租用提升数据库响应速度,缩短查询时间,这时候就需要进行分库分表。 二、如何分库分表 分库分表就是要将大量数据分散到多个数据库中,使每个数据库中数据量小响应速度快,以此来提升数据库整体性能。 核心理念就是对数据进行切分(Sharding),以及切分后如何对数据的快速定位与整合。 针对数据切分类型,大致可以分为:垂直(纵向)切分和水平(横向)切分两种。 1、垂直切分 垂直切分又细分为垂直分库和垂直分表 垂直分库 垂直分库是基于业务分类的,和我们常听到的微服务治理观念很相似,每一个独立的服务都拥有自己的数据库,需要不同业务的数据需接口调用。 而垂直分库也是按照业务分类进行划分,每个业务有独立数据库,这个比较好理解。 垂直分表 垂直分表是基于数据表的列为依据切分的,亿华云是一种大表拆小表的模式。 例如:一个order表有很多字段,把长度较大且访问不频繁的字段,拆分出来创建一个单独的扩展表work_extend进行存储。 order表: order核心表: work_extend表: 数据库是以行为单位将数据加载到内存中,这样拆分以后核心表大多是访问频率较高的字段,而且字段 长度也都较短,可以加载更多数据到内存中,增加查询的命中率,减少磁盘IO,以此来提升数据库性能。 优点: 缺点: 2、水平切分 前边说了垂直切分还是会存在单表数据量过大的问题,当我们的应用已经无法在细粒度的垂直切分时, 依旧存在单库读写、存储性能瓶颈,这时就要配合水平切分一起了。 水平切分将一张大数据量的表,切分成多个表结构相同,而每个表只占原表一部分数据,然后按不同的条件分散到多个数据库中。 假如一张order表有2000万数据,水平切分后出来四个表,order_1、order_2、order_3、order_4,每张表数据500万,以此类推。 order_1表: order_2表: order_3表: order_4表: 水平切分又分有库内分表和分库分表 库内分表 库内分表虽然将表拆分,但子表都还是在同一个数据库实例中,只是解决了单一表数据量过大的问题,并没有将拆分后的表分布到不同机器的库上,还在竞争同一个物理机的CPU、内存、网络IO。 分库分表 分库分表则是将切分出来的子表,分散到不同的数据库中,从而使得单个表的数据量变小,达到分布式的效果。 优点: 缺点: 三、数据该往哪个库的表存? 分库分表以后会出现一个问题,一张表会出现在多个数据库里,到底该往哪个库的表里存呢? 1、根据取值范围 按照时间区间或ID区间来切分,举个栗子:假如我们切分的是用户表,可以定义每个库的User表里只存10000条数据,第一个库userId从1 ~ 9999,第二个库10000 ~ 20000,第三个库20001~ 30000……以此类推。 优点: 缺点: 2、hash取模 hash取模mod(对hash结果取余数 (hash() mod N))的切分方式比较常见,还拿User表举例,对数据库从0到N-1进行编号,对User表中userId字段进行取模,得到余数i,i=0存第一个库,i=1存第二个库,i=2存第三个库….以此类推。 这样同一个用户的数据都会存在同一个库里,用userId作为条件查询就很好定位了 优点: 缺点: 四、分库分表后会有哪些坑? 1、事务一致性问题 由于表分布在不同库中,不可避免会带来跨库事务问题。一般可使用"XA协议"和"两阶段提交"处理,但是这种方式性能较差,代码开发量也比较大。 通常做法是做到最终一致性的方案,往往不苛求系统的实时一致性,只要在允许的时间段内达到最终一致性即可,可采用事务补偿的方式。 2、分页、排序的坑 日常开发中分页、排序是必备功能,而多库进行查询时limit分页、order by排序,着实让人比较头疼。 分页需按照指定字段进行排序,如果排序字段恰好是分片字段时,通过分片规则就很容易定位到分片的位置;一旦排序字段非分片字段时,就需要先在不同的分片节点中将数据进行排序并返回,然后将不同分片返回的结果集进行汇总和再次排序,最终返回给用户,过程比较复杂。 3、全局唯一主键问题 由于分库分表后,表中的数据同时存在于多个数据库,而某个分区数据库的自增主键已经无法满足全局 唯一,所以此时一个能够生成全局唯一ID的系统是非常必要的。那么这个全局唯一ID就叫分布式ID。 可以参考我之前写的这篇文章《一口气说出 9种 分布式ID生成方式,面试官有点懵了》 五、分库分表工具? 自己开发分库分表工具的工作量是巨大的,好在业界已经有了很多比较成熟的分库分表中间件,我们可 以将更多的时间放在业务实现上