一. 数据切分
1、垂直(纵向)切分
2、水平(横向)切分
垂直(纵向)切分
垂直分库
根据业务耦合性,将关联度低的不同表存储在不同的数据库
垂直分表
基于数据库中的"列"进行,某个表字段较多,可以新建一张扩展表,将不经常用或字段长度较大的字段拆分出去到扩展表中
水平(横向)切分
1、根据数值范围
2、根据数值取模
水平切分分为库内分表和分库分表,库内分表只解决了单一表数据量过大的问题,但没有将表分布到不同机器的库上,因此对于减轻MySQL数据库的压力来说,帮助不是很大,大家还是竞争同一个物理机的CPU、内存、网络IO,最好通过分库分表来解决。
二. 分库分表带来的问题
1、事务一致性问题
1)分布式事务
2)最终一致性
2、跨节点关联查询 join 问题
1)全局表
系统中所有模块都可能依赖的一些表,为了避免跨库join查询,可以将这类表在每个数据库中都保存一份。
2)字段冗余
利用空间换时间,订单表保存userId时候,也将userName冗余保存一份,
这样查询订单详情时就不需要再去查询"买家user表"了。
3)数据组装
在系统层面,分两次查询,第一次查询的结果集中找出关联数据id,然后根据id发起第二次请求得到关联数据。
最后将获得到的数据进行字段拼装。
4)ER分片
可以先确定表之间的关联关系,并将那些存在关联关系的表记录存放在同一个分片上
这样一来,Data Node1上面的order订单表与orderdetail订单详情表就可以通过orderId进行局部的关联查询了,Data Node2上也一样。
3、跨节点分页、排序、函数问题
需要先在每个分片上执行相应的函数、排序等,然后将各个分片的结果集进行汇总和再次计算,最终将结果返回。
4、全局主键避重问题
1)UUID
2)结合数据库维护主键ID表
3)Snowflake分布式自增ID算法
5、数据迁移、扩容问题
面临性能和存储的瓶颈时,才会考虑分片设计
(一般建议单个分片上的单表数据量不超过1000W)
三. 什么时候考虑切分
1、能不切分尽量不要切分
不到万不得已不用轻易使用分库分表这个大招,避免"过度设计"和"过早优化"。
分库分表之前,先尽力去做:升级硬件、升级网络、读写分离、索引优化等等。当数据量达到单表的瓶颈时候,再考虑分库分表。
2、数据量过大,正常运维影响业务访问
1)对数据库备份,如果单表太大,备份时需要大量的磁盘IO和网络IO。
2)对一个很大的表进行DDL修改时,MySQL会锁住全表,这个时间会很长,这段时间业务不能访问此表,影响很大。
3、随着业务发展,需要对某些字段垂直拆分
4、数据量快速增长
随着业务的快速发展,单表中的数据量会持续增长,当性能接近瓶颈时,就需要考虑水平切分,做分库分表了
5、安全性和可用性
鸡蛋不要放在一个篮子里。在业务层面上垂直切分,将不相关的业务的数据库分隔,不能因为一个业务把数据库搞挂而牵连到其他业务。
6、什么时候分表
当一个应用难以再细粒度的垂直切分,或切分后数据量行数巨大,存在单库读写、存储性能瓶颈,这时候就需要进行水平切分了。