乐趣区

关于java:为什么要分库分表

面试题

为什么要分库分表(设计高并发零碎的时候,数据库层面该如何设计)?用过哪些分库分表中间件?不同的分库分表中间件都有什么长处和毛病?你们具体是如何对数据库如何进行垂直拆分或程度拆分的?

面试官心理剖析

其实这块必定是扯到 高并发 了,因为分库分表肯定是为了 撑持高并发、数据量大 两个问题的。而且当初说实话,尤其是互联网类的公司面试,基本上都会来这么一下,分库分表如此广泛的技术问题,不问切实是不行,而如果你不晓得那也切实是说不过去!

面试题分析

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

说白了,分库分表是两回事儿,大家可别搞混了,可能是光分库不分表,也可能是光分表不分库,都有可能。

我先给大家抛出来一个场景。

如果咱们当初是一个小守业公司(或者是一个 BAT 公司刚衰亡的一个新部门),当初注册用户就 20 万,每天沉闷用户就 1 万,每天单表数据量就 1000,而后高峰期每秒钟并发申请最多就 10 个。我的天,就这种零碎,轻易找一个有几年工作教训的,而后带几个刚培训进去的,轻易干干都能够。

后果没想到咱们运气竟然这么好,碰上个 CEO 带着咱们走上了坎坷不平,业务倒退迅猛,过了几个月,注册用户数达到了 2000 万!每天沉闷用户数 100 万!每天单表数据量 10 万条!高峰期每秒最大申请达到 1000!同时公司还顺带着融资了两轮,进账了几个亿人民币啊!公司估值达到了惊人的几亿美金!这是小独角兽的节奏!

好吧,没事,当初大家感觉压力曾经有点大了,为啥呢?因为每天多 10 万条数据,一个月就多 300 万条数据,当初咱们单表曾经几百万数据了,马上就破千万了。然而勉强还能撑着。高峰期申请当初是 1000,咱们线上部署了几台机器,负载平衡搞了一下,数据库撑 1000QPS 也还对付。然而大家当初开始感觉有点放心了,接下来咋整呢 ……

再接下来几个月,我的天,CEO 太牛逼了,公司用户数曾经达到 1 亿,公司持续融资几十亿人民币啊!公司估值达到了惊人的几十亿美金,成为了国内往年最牛逼的明星守业公司!天,咱们太侥幸了。

然而咱们同时也是可怜的,因为此时每天沉闷用户数上千万,每天单表新增数据多达 50 万,目前一个表总数据量都曾经达到了两三千万了!扛不住啊!数据库磁盘容量一直消耗掉!高峰期并发达到惊人的 5000~8000!别开玩笑了,哥。我跟你保障,你的零碎撑持不到当初,曾经挂掉了!

好吧,所以你看到这里差不多就了解分库分表是怎么回事儿了,实际上这是跟着你的公司业务倒退走的,你公司业务倒退越好,用户就越多,数据量越大,申请量越大,那你单个数据库肯定扛不住。

分表

比方你单表都几千万数据了,你确定你能扛住么?相对不行,单表数据量太大 ,会极大影响你的 sql 执行的性能,到了前面你的 sql 可能就跑的很慢了。一般来说,就以我的教训来看,单表到几百万的时候,性能就会绝对差一些了,你就得分表了。

分表是啥意思?就是把一个表的数据放到多个表中,而后查问的时候你就查一个表。比方依照用户 id 来分表,将一个用户的数据就放在一个表中。而后操作的时候你对一个用户就操作那个表就好了。这样能够管制每个表的数据量在可控的范畴内,比方每个表就固定在 200 万以内。

分库

分库是啥意思?就是你一个库个别咱们教训而言,最多撑持到并发 2000,肯定要扩容了,而且一个衰弱的单库并发值你最好放弃在每秒 1000 左右,不要太大。那么你能够将一个库的数据拆分到多个库中,拜访的时候就拜访一个库好了。

这就是所谓的 分库分表,为啥要分库分表?你明确了吧。

用过哪些分库分表中间件?不同的分库分表中间件都有什么长处和毛病?

这个其实就是看看你理解哪些分库分表的中间件,各个中间件的优缺点是啥?而后你用过哪些分库分表的中间件。

比拟常见的包含:

  • Cobar
  • TDDL
  • Atlas
  • Sharding-jdbc
  • Mycat

Cobar

阿里 b2b 团队开发和开源的,属于 proxy 层计划,就是介于应用服务器和数据库服务器之间。应用程序通过 JDBC 驱动拜访 Cobar 集群,Cobar 依据 SQL 和分库规定对 SQL 做合成,而后散发到 MySQL 集群不同的数据库实例上执行。早些年还能够用,然而最近几年都没更新了,根本没啥人用,差不多算是被摈弃的状态吧。而且不反对读写拆散、存储过程、跨库 join 和分页等操作。

TDDL

淘宝团队开发的,属于 client 层计划。反对根本的 crud 语法和读写拆散,但不反对 join、多表查问等语法。目前应用的也不多,因为还依赖淘宝的 diamond 配置管理系统。

Atlas

360 开源的,属于 proxy 层计划,以前是有一些公司在用的,然而的确有一个很大的问题就是社区最新的保护都在 5 年前了。所以,当初用的公司根本也很少了。

Sharding-jdbc

当当开源的,属于 client 层计划,是 <a href="https://shardingsphere.apache.org/”> ShardingSphere 的 client 层计划,<a href="https://shardingsphere.apache.org/”> ShardingSphere 还提供 proxy 层的计划 Sharding-Proxy。的确之前用的还比拟多一些,因为 SQL 语法反对也比拟多,没有太多限度,而且截至 2019.4,曾经推出到了 4.0.0-RC1 版本,反对分库分表、读写拆散、分布式 id 生成、柔性事务(最大致力送达型事务、TCC 事务)。而且的确之前应用的公司会比拟多一些(这个在官网有注销应用的公司,能够看到从 2017 年始终到当初,是有不少公司在用的),目前社区也还始终在开发和保护,还算是比拟沉闷,集体认为算是一个当初也 能够抉择的计划

Mycat

基于 Cobar 革新的,属于 proxy 层计划,反对的性能十分欠缺,而且目前应该是十分火的而且一直风行的数据库中间件,社区很沉闷,也有一些公司开始在用了。然而的确相比于 Sharding jdbc 来说,年老一些,经验的锻炼少一些。

总结

综上,当初其实倡议考量的,就是 Sharding-jdbc 和 Mycat,这两个都能够去思考应用。

Sharding-jdbc 这种 client 层计划的 长处在于不必部署,运维成本低,不须要代理层的二次转发申请,性能很高 ,然而如果遇到降级啥的须要各个系统都从新降级版本再公布,各个系统都须要 耦合 Sharding-jdbc 的依赖;

Mycat 这种 proxy 层计划的 毛病在于须要部署 ,本人运维一套中间件,运维老本高,然而 益处在于对于各个我的项目是通明的,如果遇到降级之类的都是本人中间件那里搞就行了。

通常来说,这两个计划其实都能够选用,然而我集体倡议中小型公司选用 Sharding-jdbc,client 层计划轻便,而且保护成本低,不须要额定增派人手,而且中小型公司零碎复杂度会低一些,我的项目也没那么多;然而中大型公司最好还是选用 Mycat 这类 proxy 层计划,因为可能大公司零碎和我的项目十分多,团队很大,人员短缺,那么最好是专门弄集体来钻研和保护 Mycat,而后大量我的项目间接通明应用即可。

你们具体是如何对数据库如何进行垂直拆分或程度拆分的?

程度拆分 的意思,就是把一个表的数据给弄到多个库的多个表里去,然而每个库的表构造都一样,只不过每个库表放的数据是不同的,所有库表的数据加起来就是全副数据。程度拆分的意义,就是将数据平均放更多的库里,而后用多个库来扛更高的并发,还有就是用多个库的存储容量来进行扩容。

垂直拆分的意思,就是把一个有很多字段的表给拆分成多个表,或者是多个库下来。每个库表的构造都不一样,每个库表都蕴含局部字段。一般来说,会将较少的拜访频率很高的字段放到一个表里去,而后将较多的拜访频率很低的字段放到另外一个表里去。因为数据库是有缓存的,你拜访频率高的行字段越少,就能够在缓存里缓存更多的行,性能就越好。这个个别在表层面做的较多一些。

这个其实挺常见的,不肯定我说,大家很多同学可能本人都做过,把一个大表拆开,订单表、订单领取表、订单商品表。

还有 表层面的拆分 ,就是分表,将一个表变成 N 个表,就是 让每个表的数据量管制在肯定范畴内,保障 SQL 的性能。否则单表数据量越大,SQL 性能就越差。个别是 200 万行左右,不要太多,然而也得看具体你怎么操作,也可能是 500 万,或者是 100 万。你的 SQL 越简单,就最好让单表行数越少。

好了,无论分库还是分表,下面说的那些数据库中间件都是能够反对的。就是基本上那些中间件能够做到你分库分表之后,中间件能够依据你指定的某个字段值 ,比如说 userid, 主动路由到对应的库下来,而后再主动路由到对应的表里去

你就得考虑一下,你的我的项目里该如何分库分表?一般来说,垂直拆分,你能够在表层面来做,对一些字段特地多的表做一下拆分;程度拆分,你能够说是并发承载不了,或者是数据量太大,容量承载不了,你给拆了,按什么字段来拆,你本人想好;分表,你考虑一下,你如果哪怕是拆到每个库里去,并发和容量都 ok 了,然而每个库的表还是太大了,那么你就分表,将这个表离开,保障每个表的数据量并不是很大。

而且这儿还有两种 分库分表的形式

  • 一种是依照 range 来分,就是每个库一段间断的数据,这个个别是按比方 工夫范畴 来的,然而这种个别较少用,因为很容易产生热点问题,大量的流量都打在最新的数据上了。
  • 或者是依照某个字段 hash 一下平均扩散,这个较为罕用。

range 来分,益处在于说,扩容的时候很简略,因为你只有准备好,给每个月都筹备一个库就能够了,到了一个新的月份的时候,自然而然,就会写新的库了;毛病,然而大部分的申请,都是拜访最新的数据。理论生产用 range,要看场景。

hash 散发,益处在于说,能够平均分配每个库的数据量和申请压力;害处在于说扩容起来比拟麻烦,会有一个数据迁徙的过程,之前的数据须要从新计算 hash 值重新分配到不同的库或表。

我是 Java 工程师,学习理解更多 Java 基础知识能够退出我的 Java 老手交换群:3907814,任何问题都能够在外面问

退出移动版