1.为啥要分表呢?
一个表的数据量级达到几百万的时候,性能就比较差了,这个时候就可以考虑分表了,就是把一个表的数据拆分到多个表里面去,比如用用户id做hash,把不同的用户id分、hash到不同的表里面去。
2.为什么要分库呢?
当一个数据库支撑到2000并发的时候,就要考虑做分库了,就是把一个库里面的数据拆分到多个库里面去。
3.有啥分库分表的中间件呢?
4.如何对数据进行水平拆分或垂直拆分?
水平拆分就是把一个数据库的表拆分到多个库的多个表里面去,所有的库表数据加起来才是全部的数据,其实就是把数据更均匀的放到更多的库里面去,用多个库扛住更高的并发,也能实现存储的扩容。
垂直拆分就是把一张表按照字段来拆分,把不同的字段存储到不同的库或者表上面去。一般来说,会挑出来几个访问频率高的字段放到一张表里面去,因为数据库是有缓存的,你访问频率高的行字段越少,就可以在缓存保存更多的行。这种拆分一般在表层面做的更多一些。
5.分库分表的方式
有两种,一种是range,就是每个库一段连续的数据,比如按照时间的范围来,但是这种方式比较容易产生热点问题,就是大部分请求都去冲着最新的数据去的,另一种是按照某个字段做hash,这个比较常用。
优缺点:
range来分,好处在于说,后面扩容的时候,就很容易,因为你只要预备好,给每个月都准备一个库就可以了,到了一个新的月份的时候,自然而然,就会写新的库了;缺点,但是大部分的请求,都是访问最新的数据。实际生产用range,要看场景,你的用户不是仅仅访问最新的数据,而是均匀的访问现在的数据以及历史的数据。
hash分法,好处在于说,可以平均分配没给库的数据量和请求压力;坏处在于说扩容起来比较麻烦,会有一个数据迁移的这么一个过程。
5.怎么把单库单表迁移到分库分表上去?
假设,现在有一个单表600万数据的表,你现在把他分了三个库,每个库四个表,单表50万。怎么迁移?
一般来说就是双写,就是在线上系统里面,之前所有写库的地方,增删改操作,都除了对老库增删改,都加上对新库的增删改,,同时写俩库。
然后系统部署之后,新库数据差太远,用导数工具,跑起来读老库数据写新库,写的时候要根据gmt_modified这类字段判断这条数据最后修改的时间,除非是读出来的数据在新库里没有,或者是比新库的数据新才会写。
接着导完一轮之后,有可能数据还是存在不一致,那么就程序自动做一轮校验,比对新老库每个表的每条数据,接着如果有不一样的,就针对那些不一样的,从老库读数据再次写。反复循环,直到两个库每个表的数据都完全一致为止。
接着当数据完全一致了,就ok了,基于仅仅使用分库分表的最新代码,重新部署一次。
6.动态扩容缩容的分表方案是什么?
如果你分库分表之后现在这些库和表又支撑不住了,要继续扩容怎么办?可能就你的每个库的容量又快满了,或者是你的表数据量又太大了,也可能是你每个库的写并发太高了,你得继续扩容。
可以一开始上来就是32个库,每个库32个表,1024张表,根据某个id先根据32取模路由到库,再根据32取模路由到库里的表。
无论是并发支撑还是数据量支撑都没问题,每个库正常承载的写入并发量是1000,如果每个库承载1500的写并发,32 * 1500 = 48000的写并发,接近5万/s的写入并发,前面再加一个MQ,削峰,每秒写入MQ 8万条数据,每秒消费5万条数据。
1024张表,假设每个表放500万数据,在MySQL里可以放50亿条数据。
哪怕是要减少库的数量,就按倍数缩容就可以了,然后修改一下路由规则。