为什么要分库分表

在业务场景中,mysql的单表数据量出现在千万级左右查询数据就会出现瓶颈。在各种优化后,可以考虑对数据库进行拆分。

1.水平拆分:就是把一张表的数据拆成两张表

MySQL 分库分表分区 mysql 分库分表实现_MySQL 分库分表分区

2.垂直拆分:将表中的某些字段,单独拆分出来,并通过某个字段和原表建立联系

MySQL 分库分表分区 mysql 分库分表实现_mysql_02

分库分表常用思路

1.hash取模方案
hash的方案就是对指定的路由key(通常为主键id)对分表总数进行取模。
优点:某个表不会出现热点问题(某个表被频繁访问,其他表访问较少的情况)
缺点:对于以后要扩容会比较麻烦,增加表的时候要对所有数据重新hash

2.range范围方案

简单来说就是1-1000万的数据放在1数据库并以此类推。

MySQL 分库分表分区 mysql 分库分表实现_数据库_03


**优点:**有利于将来扩容,有新数据就直接加入就好了

**缺点:**缺点也很明显,有可能出现热点问题。比如刚加进来的数据经常使用之类的问题

3.两者结合的方案
那能不能考虑把两个的有点结合过来,又把去掉两者的缺点?即不容进行数据迁移,又不存在热点问题?其实还有一个现实需求,能否根据服务器的性能以及存储高低,适当均匀调整存储呢?

我们定义一个Group的概念,一个Group包含了一些分库和分表,如下图:

MySQL 分库分表分区 mysql 分库分表实现_数据_04


上图有几个关键点:

一个Group01可以存放4000w个数据,Group01有三个DB,共10table。那么可以通过id范围确定在哪个group,然后id%10哪个db。再根据范围确定哪个table。简单来说就是整体有序,局部用hash打乱,当扩容的时候只要加group就好了。

MySQL 分库分表分区 mysql 分库分表实现_取模_05


上图中id一千万以内的都被我们设计的流程均匀的分在了三个的table0中。然后就是为什么对表的总数取模?因为每台服务器的性能有差异,对表取模,那表多的服务器就更能被使用到。

MySQL 分库分表分区 mysql 分库分表实现_数据库_06


图中我们对10进行取模,如果值为【0,1,2,3】就路由到DB_0,【4,5,6】路由到DB_1,【7,8,9】路由到DB_2。现在小伙伴们有没有理解,这样的设计就可以把多一点的数据放到DB_0中,其他2个DB数据量就可以少一点。DB_0承担了4/10的数据量,DB_1承担了3/10的数据量,DB_2也承担了3/10的数据量。整个Group01承担了【0,4000万】的数据量

其实上面设计思路理解了,扩容就已经出来了;那就是扩容的时候再设计一个group02组,定义好此group的数据范围就ok了。

MySQL 分库分表分区 mysql 分库分表实现_数据_07

使用sharding-sphere实现