一、为什么要进行分库分表
(1)解决高并发问题
(2)数据库数据量过大
二、拆分方式
(1)垂直拆分,通常是把一个有很多字段的表给拆分成多个表,或者是多个库上去。每个库表的结构都不一样,每个库表都包含部分字段。一般情况下,会将较少的访问频率很高的字段放到一个表里去,然后将较多的访问频率很低的字段放到另外一个表里去。因为数据库是有缓存的,你访问频率高的行字段越少,就可以在缓存里缓存更多的行,性能就越好。这个一般在表层面做的较多一些。
(2)水平拆分,又分为数据库水平拆分和表水平拆分。通常是把一个表的数据给弄到多个库的多个表里去,但是每个库的表结构都一样,只不过每个库表放的数据是不同的,所有库表的数据加起来就是全部数据。水平拆分的意义,就是将数据均匀放更多的库里,然后用多个库来抗更高的并发,还有就是用多个库的存储容量来进行扩容。
三、分库分表中间件
比较常用的有四种:cobar、TDDL、atlas、sharding-jdbc、mycat
这里只介绍比较常见的sharding-jdbc和mycat
(1)sharding-jdbc:当当开源的,属于client层方案。确实之前用的还比较多一些,因为SQL语法支持也比较多,没有太多限制,而且· 目前推出到了2.0版本,支持分库分表、读写分离、分布式id生成、柔性事务(最大努力送达型事务、TCC事务)。而且确实之前使用的公司会比较多一些(这个在官网有登记使用的公司,可以看到从2017年一直到现在,是不少公司在用的),目前社区也还一直在开发和维护,还算是比较活跃,个人认为算是一个现在也可以选择的方案。
(2)mycat:基于cobar改造的,属于proxy层方案,支持的功能非常完善,而且目前应该是非常火的而且不断流行的数据库中间件,社区很活跃,也有一些公司开始在用了。但是确实相比于sharding jdbc来说,年轻一些,经历的锤炼少一些。
四、分库分表拆分方式
(1)hash分法,根据某个字段hash一下均匀分散,
(2)range分法,根据每个库一段连续的数据,这个一般是按比如时间范围来的,但是这种一般较少用,因为很容易产生热点问题,大量的流量都打在最新的数据上了
各自的优缺点:
hash分法,好处在于说,可以平均分配没给库的数据量和请求压力;坏处在于说扩容起来比较麻烦,会有一个数据迁移的这么一 个过程
range来分,好处在于说,后面扩容的时候,就很容易,因为你只要预备好,给每个月都准备一个库就可以了,到了一个新的月份 的时候,自然而然,就会写新的库了;缺点,但是大部分的请求,都是访问最新的数据。实际生产用range,要看场景,你的用户不是仅仅访问最新的数据,而是均匀的访问现在的数据以及历史的数据
二、谈一谈开发中遇到的问题
比如某知名OTA公司,注册用户1000W,每天有10%的用户去访问系统,按照28定律,高峰时间段大约会有80W用户访问系统,每人访问4个小时,每人分别提交20次表单,也就是4个小时提交1600W次请求,QPS(单位时间内处理的请求数)为1200,按照每次请求访问3次数据库来算,每秒请求数据库3600次。
通常来说,对于普通的16核32G机器配置,一般的现实经验是:不要让每秒的数据库访问数超过2000。
那么这样,我们通常会想到两种措施:
系统层面:多部署几台服务器,通过集群的方式来扩容,通过负载均衡让请求均匀分布。
采用MQ,来调用异步写系统,达到解耦、异步、削峰的目的
数据库层面:采用分库分表+读写分离。
(1)方案1:部署3台机器,两台数据库,每秒请求数1200,看似解决了单机高并发问题。
过了一段时间发现:
(1)mysql单机磁盘容量快满了。
(2)数据库单表新增数量越来越多,达到了千万级别,数据库性能越来越差,SQL越跑越慢。
我们继续设计~
假设原先单表时,每个表的数据量有3000万条,每天新增数据量120万,我们部署了6台服务器,也就是每台数据库每日新增数据数20万。一年下来,增加七千万条数据。。。还是太大了。那就想到了拆分多表。