面试题——为什么要分库分表

面试题

为什么要分表分库(设计高并发系统的时候,数据库层面该如何设计)?使用过哪些分表分库中间件?不同的分表分库中间件都有什么优点和缺点?你们是如何对具体的数据库进行垂直拆分和水平拆分的?

面试官心理分析

其实这一块内容主要就是针对高并发的,因为分库分表主要解决的问题就是支撑高并数据量大两个问题。而且现在如果是去互联网公司面试的话,基本上都是会问一下的。

面试题剖析

为什么要分库分表?(设计高并发系统的时候,数据库层面该如何设计?)

说白了,分库和分表是两码事,可能在实际项目中,只分库不分表,也可能是只分表不分库。分表和分库对应的是不同的场景,也是为了解决不同的问题。

分表

比如现在系统中的单表数据量已经有上亿条了,你的单表数据量过大,会直接影响SQL的执行性能,依照经验,当单表数据量过百万的时候,就会逐渐出现性能问题,就需要考虑分表。
分表就意味着讲数据拆分开来,进行数据分片,每一部都包含少量的数据,可以将
每个表的数据控制在一定的范围内。

分库

分库是什么意思?根据生产经验一台数据库的并发量,大概撑的到2000左右,否则就可能出现崩溃问题。一个健康的单库并发量最好在1000左右,不要太大。可以将一个库的数据拆分到多个库,访问的时候只访问一个库就行了。

- 分表分库前 分表分库后
并发支撑情况 MySQL单机部署,扛不住高并发 MySQL从单机到多机,能承受的并发增加了多倍
磁盘使用情况 MySQL的磁盘空间几乎撑满 拆分为多个库,数据库磁盘使用率大大降低
SQL执行性能 单表数据量太大,SQL越跑越慢 单表数据量减少,SQL执行效率明显提升

用过哪些分库分表中间件,不同的分库分表中间件都有什么优点和缺点?

这个其实就是技术选型的问题,知道各种的分库分表中间件,以及对他们的长处短处做到心中有数。
比较常见的有:

  • Cobar
  • TDDL
  • Atlas
  • Sharding-Sphere(jdbc)
  • Mycat
Cobar

阿里b2b团队发开和开源的,属于proxy层方案,就是介于应用服务器和数据库服务器之间。应用程序通过JDBC驱动访问Cobar集群,Cobar根据SQL和分库规则对SQL做分解,然后分发到MySQL集群不同的数据库实例上执行。目前已经没什么维护了。

TDDL

淘宝团队开发,属于client层方案。支持基本的crud愈发和读写分离,但不支持join、多表查询等语法。目前使用的也不多。

Altas

360开源的,属于proxy层方案,以前是有一些公司在用的,但是确实有一个很大的问题就是社区最新的维护都在5年前了。所以现在用的公司比较少。

Sharding-sphere

当当开源的,属于client层方案,目前已经更名为shardingSphere。因为SQL语法支持的比较多,而且没有太多限制,使用的比较多。

MyCat

基于Cobar改造,属于proxy层方案,支持的功能非常完善,而且目前应该是非常火的而且不断流行的数据库中间件,社区很活跃,也有一些公司开始在用了。但是相对于Sharding-sphere来说要年轻一些,发现时间相对少一些。

总结

其实业界主流的分库分表中间件只有两个sharding-sphereMyCat

sharding-sphere:这中client层的方案的优点在于不用部署,运维成本低,不需要代理层的二次转发,性能很高,但是如果升级什么的,整个系统都需要重新发布,对sharding-sphere的耦合度比较高。
MyCat:这种proxy层方案的缺点在于需要部署,自己运维一套中间件,运维成本高,但是好处在于对于各个项目都是透明的,如果遇到升级之类的都是自己中间件那里搞就行了。

通常来讲,这两种方案都是可行的。对于小公司来说,sharding-sphere比较合适,性能高,运维成本低,不需要额外的成本,而且中小型公司项目量和业务复杂度也没有特别大。但是大公司最好还是选用proxy这种方案,因为大公司可能项目比较多,花点人力和物力来维护一套数据中间件,这样对于项目来说就是透明的,还是非常值得的。

你们具体是如果对数据库进行垂直拆分和水平拆分的?

水平拆分的意思,就是把一个表的数据弄到多个表(库)里面去,每个表的数据结构都是一样的,只不过数据量不同,所有的表加起来,就是全部的数据。水平拆分的意义,就是将数据均匀的分布在多个库里面,让更多的库来抗高并发,还有就是用多个库的存储量来进行扩容。

垂直拆分的意思,就是把一个有很多字段的表拆分成多个表,或者是多个库上去。每个库包含的是部分字段。一般来说,将访问量比较高的字段放入一个表中,将访问量比较低的字段放入一个表中。因为数据库是有缓存的,而缓存是有限的资源,当行数越少的时候,性能就越好。
其实垂直拆分的情况,还是很常见的,将一张大表拆开,比如订单表,订单支付表,订单商品表。
水平拆分是保证了单表数据量不会太高,保证了SQL执行的性能。无论是分库还是分表,上面的中间件都是支持的。基本上上述中间件可以做到分库分表之后,中间件可以根据你给定的某个值,然后自动路由到对应的库上,然后再自动路由到对应的表里。
你就得考虑一下,在项目中该如何做到分库分表?一般来说,垂直拆分,你可以在表面层来做,对一些字段特别多的表可以做垂直拆分。水平拆分,可以说是并发承受不了,或者数据量太多了,可以做水平拆分。

而且这里还有两种分库分表方式

  • 一种是按照range来分,就是每个库一段连续的数据,这个一般是按照时间范围来的,但是用的比较少,因为可能会产生热点问题,大量的流量都打到最新的数据上去。
  • 或者是按照某个字段hash一下均匀分散,这个较为常用。

range来分,好处在于,扩容的时候很简单,只需要准备好,比如按照时间间隔,每个月分一个库就可以了。缺点是可能出现热点倾斜,大量的请求都访问的是最新的库。

hash来分,好处在于,可以平均分配每个库的数据量和请求压力;坏处在于扩容起来相对比较麻烦,会有一个rehash所带来的数据迁移问题。

发布了17 篇原创文章 · 获赞 0 · 访问量 319

猜你喜欢

转载自blog.csdn.net/qq_26375325/article/details/105227842