分库分表面试题

什么是分库分表?/为什么分库分表?

随着业务的发展,数据量越来越大,数据库并发越来越高,单库单表降低了查询速度,影响了客户体验,所以要进行分库分表。首先要清楚,分库和分表是两回事,是两个独立的概念。分库和分表都是为了防止数据库服务因为同一时间的访问量(增删查改)过大导致宕机而设计的一种应对策略。

为什么要分库

按一般的经验来说,一个单库最多支持并发量到2000,且最好保持在1000。如果有20000并发量的需求,这时就需要扩容了,可以将一个库的数据拆分到多个库中,访问的时候根据一定条件访问单库,缓解单库的性能压力。

为什么要分表

分表也是一样的,如果单表的数据量太大,就会影响SQL语句的执行性能。一般而言,表数据量超过500w就需要分表。分表就是按照一定的策略将单表的数据拆分到多个表中,查询的时候也按照一定的策略去查询对应的表,这样就将一次查询的数据范围缩小了。比如按照用户id来分表,将一个用户的数据就放在一个表中,crud先通过用户id找到那个表在进行操作就可以了。这样就把每个表的数据量控制在一定范围内,提升SQL语句的执行性能。

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

分库分表常见的中间件有:cobar、TDDL、atlas、sharding-jdbc和mycat等。

cobar

cobar是阿里的b2b团队开发和开源的,属于proxy层方案,介于应用服务器和数据库服务器之间。应用程序通过JDBC驱动访问cobar集群,cobar根据SQL和分库规则对SQL做分解,然后分发到MySQL集群不同的数据库实例上执行。cobar并不支持读写分离、存储过程、跨库join和分页等操作。早些年还可以用,但是最近几年都没更新了,基本没啥人用,算是淘汰了。

TDDL

TDDL是淘宝团队开发的,属于client层方案。支持基本的crud语法和读写分离,但是并不支持join、多表查询等语法。目前使用的也不多,因为使用还需要依赖淘宝的diamond配置管理系统。

atlas

atlas是360开源的,属于proxy层方案。以前是有一些公司再用的,但是社区最新的维护都在5年前了,现在用的公司也基本没有了。

sharding-jdbc

sharding-jdbc是当当开源的,属于client层方案。这个中间件对SQL语法的支持比较多,没有太多限制。2.0版本也开始支持分库分表、读写分离、分布式id生成、柔性事务(最大努力送达型事务、TCC事务)。目前社区也还一直在开发和维护,算是比较活跃,是一个现在也可以选择的方案。

mycat

mycat是基于cobar改造的,属于proxy层方案。其支持的功能十分完善,是目前非常火的一个数据库中间件。社区很活跃,不断在更新。相比于sharding-jdbc来说,年轻一些,经历的锤炼也少一些。

总结

综上所述,现在建议考量使用的就是sharding-jdbc和mycat。

sharding-jdbc这种client层的优点在于不用部署,因此运维成本也就比较低。同时因为不需要代理层的二次转发请求,性能很高。但是如果遇到升级的话,需要各个系统都重新升级版本再发布,因为各个系统都需要耦合sharding-jdbc的依赖。

mycat这种proxy方案的缺点在于需要部署,因此运维成本也就比较高。但是优点在于其对于各个项目是透明(解耦)的,如果要升级的话只需要在中间件处理就行了。

通常来说,这两个方案都是可以选用的。但是建议中小型公司选用sharding-jdbc比较好,因为client层方案轻便,维护成本低;建议中大型公司选用mycat比较好,因为proxy层方案可以应对多个系统和项目大量使用,虽然维护成本相对来说会较高,但是中大型公司还缺这点人力吗。

具体如何对数据库进行垂直拆分或水平拆分?

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

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

垂直分表:可以吧一个宽表的字段按访问频次,是否是大字段的原则拆分为多个表,这样既能使业务清晰,还能提升部分性能,拆分后,尽量从业务角度避免联查,否则性能方面将得不偿失。

垂直分库:可以把多个表按业务耦合松紧归类,分别存放在不同的库,这些库可以分布在不同服务器,从而使访问压力被多服务器负载,大大提升性能,同事能提高整体架构的业务清晰度,不同的业务可根据自身情况定制优化方案,但是他需要解决跨库带来的所有复杂问题。

水平分库:可以把一个表的数据(按数据行)分到多个不同的库,每个库只有这个表的部分数据,这些库可以分布在不同的服务器上,从而使访问压力被多服务器负载,大大提升性能,他不仅需要解决跨库带来的所有复杂问题,还要解决数据路由的问题(数据路由问题后边介绍)。

水平分表:可以把一个表的数据(按数据行)分到同一个数据库的多张表中,每个表只有这个表的部分数据,这样做能小幅提升性能,他仅仅作为水平分库的一个补充优化。

分库分表的两个方案

这里说一下两种分库分表的方案和它们的优缺点。

1.按照range来分。比如说按照时间范围来分库分表,每个库表中存放的都是连续时间范围的数据。但是这种方式一般很少用,因为很容易会产生热点问题,大量的流量都打在最新的数据上了。这种方案的优点在于扩容的时候非常简单,比如只要预备好每个月都准备一个库就可以了,到了下一个新的月份自动将数据写入新的库。缺点则是,如果大部分请求都是访问最新的数据,那么在这里,分库分表的设计目的就只是简单的扩容,而不是为了应对高并发了。

2.按照hash分发。按照某个字段的hash值均匀分散,这个较为常用。优点在于可以平均分配每个库表的数据量和请求压力;缺点在于扩容比较麻烦,因为会存在一个数据迁移的过程,即之前的数据需要重新计算hash值并重新分配到不同的库表中。

目前准备做数据库水平切分,需要注意什么关键问题?

(1)需要注意分库patition key的选取,要保证两个均衡:数据量的均衡,请求量的均衡。

(2)库后,需要注意分之前用SQL满足的需求是否还能满足,需要怎么改进满足,例如max, min, avg, sum都需要在服务层再做一次聚合。

设定网站用户数量在千万级,但是活跃用户数量只有1%,如何通过优化数据库提高活跃用户访问速度?

(1)可以使用MySQL的分区,把活跃用户分在一个区,不活跃用户分在另外一个区,本身活跃用户区数据量比较少,因此可以提高活跃用户访问速度。
(2)还可以水平分表,把活跃用户分在一张表,不活跃用户分在另一张表,可以提高活跃用户访问速度。

分库分表之后,id 主键如何处理?

(1)数据库自增 id

这个就是说你的系统里每次得到一个 id,都是往一个库的一个表里插入一条没什么业务含义的数据,然后获取一个数据库自增的一个 id。拿到这个 id 之后再往对应的分库分表里去写入。

(2)设置数据库 sequence 或者表自增字段步长

可以通过设置数据库 sequence 或者表的自增字段步长来进行水平伸缩。

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

一般来说,垂直拆分,你可以在表层面来做,对一些字段特别多的表做一下拆分;水平拆分,你可以说是并发承载不了,或者是数据量太大,容量承载不了,拆了,按什么字段来拆。分表,你如果哪怕是拆到每个库里去,并发和容量都ok了,但是每个库的表还是太大了,那么你就分表,将这个表分开,保证每个表的数据量并不是很大。

分库分表的拆分方式有?他们分别主要解决什么问题?

(1)水平切分,主要解决单表过大造成的性能问题,单表过大造成的单服务器空间问题。

(2)垂直切分,主要解决表与表之间资源争用问题,锁争用机率小,实现核心与非核心的分级存储,如UDB登陆库拆分成一级二级三级库,数据库同步压力问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值