1.什么是分库分表
分库:
就是数据库分成多个数据库,部署到不同的机器上。
例如:用户表,订单表,积分表,商品表:然后分到:用户库,订单库,积分库,商品库。
分表:
一个表分成多个表
例如:订单表:分成分表1,分表2,分表3;
为什么分库:
在做任何事情之前我们都要思考,为什么做?为什么要拆分表,拆分表的原因是什么?我们不能可能无缘无故的做分库分表的。
当业务量巨大的增加,数据库就有一定的性能问题了,这时候我们要考虑拆分数据库,
1.随着业务量的增加,mysql的磁盘会有性能问题,拆成多个库,就可以降低磁盘的使用率。
2.数据库的连接数,是有控制的,太多的连接数会导致性能问题:会报错,例如:too many connection
为什么分表
如果单表数据量过大,查询和存储都会有性能问题,如果做了优化还是无法解决性能问题,这时候要考虑分表了,一般千万级别的数据,就要分表。
什么时候分库分表
对于MYSQL单标最多存储10亿级别,但是如果单表真的存储10亿性能会非常的差,一般数据量是千万级别,B+树索引的高度就会到了3层以上了,查询的时候会多查磁盘的次数,SQL会变慢。
实际阿里规定:单表超过500万,表容量2G就推荐分;
但是并不是死的,所有的都这样,要按照实际,如果我们的业务几年都打不到500万不用考虑分表的问题。
什么类型的业务考虑分库分表?
流水表,用户表,
如何选择分表键
分表键就是用来分库分表的,就是分的依据,依据哪个维度分?
按照userID,按time,按照区域;
问题分表后,用户通过非分表键怎么查询:
例如我们按照userID来分表,但是我们登录是手机号登录,怎么通过手机号进行各个表的查询呢?
1.遍历所有的表,不建议,太笨的方法。
2.将用户信息冗余同步到ES,然后通过ES查询;
如何选择分表的策略:
1.按照范围分
1.按照ID1-300万分,这样分
2.按照时间,比如**年分
- 优点:
有利于扩容 - 缺点:
-一段时间有的数据都只会出现在一个表里面,如果用户查询近期数据,肯定还是查询某一个表。
2.按照hash取模分
(字段,字段2,字段3,字段4,)作为key,对总表进行取模,把数据分散到各个表里面。hash/4
例如:hash(字段1)/4,=1,就放第一个表,得到3就放在第三个表。
- 优点:不会存在明显的某个表过热的问题
- 缺点:表数据量后续达到瓶颈,需要扩容比较麻烦。
3.一致性hash
接上述问题:如果开始我们只有10个表,后边需要扩充到20个,那么之前10个表的数据,就有可能被重复分配到别的表里面去。
为了解决扩容问题:需要扩容迁移,可以使用hash一致性思想来解决。
分库后,事务问题如何解决?
本地事务无效,需要使用分布式事务。
分库分表遇到join怎么办?
1.字段冗余:空间换时间,就是吧关联的字段放到主表里面,就不用去关联了。
2.全局表:比如系统所有的模块都可能会依赖到一个基础表。
3.数据抽象同步:A表a和B表b,定时将表做同步,将数据汇合,生成新的表,一般可以借助ETL工具。
4.应用层代码组装:分开多次查询,调用不同模块服务,获取到数据后,代码层进行字段计算拼装。
聚合函数问题
1.使用mycat, shardingSphere 等,这些中间件提供了跨分片查询支持,一定程度简化了操作。
分库分表后的分页问题:
1.在各个数据库节点,查询到对应的结果后,代码汇总,然后在分页。缺点:返回多数据,增大网络传输。
2.方法二:查询第一页的时候,和方案一一样,但是下一页,需要把当前最大的创建时间传过来,然后每个节点,都查询大于创建时间的一页数据,接着汇总,内存排序返回。
分布ID
数据库被分后,不能使用自身的主键生成机制,可以使用简单的UUID,或者分布式ID。
分库分表使用的中间件?
1.Sharding-JDBC
2.cobar
3.Mycat
4.Atlas
5.TDDL
6.Vitess
如何评估分库数量
对于mysql一般5千万,就非常大了,分多少,取决于处理能力。
分的少起不到优化的作用,分的过多,跨多库访问。,一般建议4-10个库。
分表要停服务?
1.开关,控制访问新的DAO层,还是老的DAO层
2.投产,开启双写,就是老表,和分表都写入,日志临时表记录新表的ID,旧表小于这个值的数据,就是要迁移的数据。
3.通过脚本,迁移
4.停止读旧表,改读新表,不要立即停止写老的,需要双写观察一段时间。
5.读写一段时间没有问题,可以停止写旧表啦。