面试官:说说Mysql数据库分库分表,而且会有哪些问题?

以前一篇文章已经谈到了数据库集群之主从集群也就是读写分离,也提到了读写分离其实只是分担了访问的压力,可是存储的压力没有解决。redis

存储的压力说白了就是随着系统的演化,需求的增长,可能表的数量会逐渐增多,好比一段时间上个新功能就得加个表。而且随着用户量的增多相似用户表的行数确定会增多,订单表的数据确定会随着时间而增多,当这种数据量达到千万甚至上亿的时候,读写分离就已经知足不了,读写性能降低严重。sql

也就是一台服务器的资源例如CPU、内存、IO、磁盘等是有限的,因此这时候分库分表就上啦!数据库

分库

分库讲白了就是好比如今你有一个数据库服务器,数据库中有两张表分别是用户表和订单表。若是要分库的话如今你须要买两台机子,搞两个数据库分别放在两台机子上,而且一个数据库放用户表,一个数据库放订单表 服务器

这样存储压力就分担到两个服务器上了,可是会带来新的问题,因此东西变复杂了都会有新的问题产生。架构

一、联表查询问题 也就是join了,以前在一个数据库里面能够用上join用一条sql语句就能够联表查询获得想要的结果,可是如今分为多个数据库了,因此join用不上了。就好比如今要查注册时间在2019年以后用户的订单信息,你就须要先去数据库A中用户表查询注册在2019年以后的信息,而后获得用户id,再拿这些id去数据库B订单表中查找订单信息,而后再拼接这些信息返回。因此等于得多写一些代码了。分布式

二、事务问题 搞数据库基本上都离不开事务,可是如今不一样的数据库事务就不是之前那个简单的本地事务了,而是分布式事务了,而引入分布式事务也提升了系统的复杂性,而且有些效率不高还会影响性能例如Mysql XA。还有基于消息中间件实现分布式事务的等等这里不展开讲述。性能

分表

咱们已经作了分库了,可是如今状况是咱们的表里面的数据太多了,就一不当心你的公司的产品火了,像抖音这种,全部用户若是就存在一张表里吃不消,因此这时候得分表。分别又分垂直分表和水平分表。优化

垂直分表

垂直分表的意思形象点就像坐标轴的y轴,把x轴切成了两半,对应到咱们的表就是好比咱们表有10列,如今一刀切下去,分红了两张表,其中一张表3列,另外一张表7列。架构设计

这个一刀切下去让两个表分别有几列不是固定的,垂直分表适合表中存在不经常使用而且占用了大量空间的表拆分出去。设计

就拿头条的用户信息,好比用户表只有用户id、昵称、手机号、我的简介这4个字段。可是手机号和我的简介这种信息就属于不太经常使用的,占用的空间也不小,我的简介有些人写了一坨。因此就把手机号和我的简介这两列拆分出去。

那垂直分表影响就是以前只要一个查询的,如今须要两次查询才能拿到分表以前的完整用户表信息。

水平分表

水平分表的意思形象点就像坐标轴的x轴,把y轴切成了两半(固然不只限于切一刀,能够切好几份)。也拿用户表来讲好比如今用户表有5000万行数据,咱们切5刀,分红5个表,每一个表1000万行数据。

水平分表就适合用户表行数不少的状况下,通常单表行数超过5000万就得分表,若是单表的数据比较复杂那可能2000万甚至1000万就得分了,这个得看实际状况有些表很简单可能一亿行都不用分。因此当一个表行数超过千万级别的时候关注一下,若是没有性能问题就能够再等等看,不要急着分表,由于分表会是带来不少问题。

水平分表的问题比垂直分表就更烦了。

要考虑怎么切,讲的高级点就叫路由

一、按id也就是范围路由,好比id 值1~999万的放一张表,1000万~1999放一张表,一次类推。这个得试的,由于范围分的大了,可能性能还有问题,范围分的小了。。那表不得多死。

这种分法的好处就是容易切啊,简单粗暴,之后新增的数据分表都不会影响到以前的数据,以前的数据都不须要移动。

二、哈希路由 就是取几列哈希一下看看数据哪一个库,好比拿id来作哈希,1500取余8等于4,因此这条记录就放在user_4这个表中,2011取余8等于3,因此这条记录就放在user_3中。这种分法好处就是分的很均匀,基本上每一个表的数据都差很少,可是之后新增数据又得分表了咋办,之前的数据都得动,比较烦!

三、搞一张表来存储路由关系 仍是拿用户表来讲,就是弄一个路由表,里面存userId和表编号,表示这个userId是这张user表的的。这种方式也简单,以后又要分表了以后改改路由表,迁移一部分数据。可是这种方法致使每次查询都得查两次,而且若是路由表太大了,那路由表又成为瓶颈了!

再说说查询时候的问题。

好比你要查注册时间最先的前100名用户,这就等于你得在水平分的每一张表都order by 一下注册时间而且取100个,而后再把每一个表的100个结果对比一下获得最终的结果。首先操做变麻烦了,之前一个order by就搞定的事情如今变的复杂了,并且还得考虑一个因素就是时间的问题,若是你拆成了20个表,那你得执行20个order by,若是是串行执行的话,这个时间开销也是个问题!

分库分表的实现

具体实现也分为程序代码封装、数据库中间件封装。实现难度会比读写分离更大,至于两种封装的比较在讲读写分离时候已经说了,这里再也不赘述。

总结

说了这么多好像分库分表一点都很差啊,没错会引入不少问题,因此在架构设计要遵循演化原则,任何东西都不是一蹴而就的,在不一样场景适配不一样的架构,架构只有合适的,没有一个架构能够适配任何场景。

在软件中简单够用就是好的,技术没有贵贱,不是用了分布式就牛逼,越复杂的系统维护的成本和难度越高,出现问题的概率越大。这种架构的演化每每都是被用户所驱动的,能够说是"不得已而为之"。

基本上单机数据库能够支撑10万用户量级别。因此通常状况下像数据库吃不消就升级硬件,优化数据库配置、优化代码、引入redis等。只有在真的不行了才上这些更复杂的东西。


若有错误欢迎指正! 我的公众号:yes的练级攻略

相关文章
相关标签/搜索