分库分表最全指南

分库分表最全指南

      • 一、数据库瓶颈
        • 1、IO瓶颈---分库和垂直分表
        • 2、CPU瓶颈---SQL优化和水平分表
      • 二、什么时候分库分表?
      • 三、分库分表
        • 1、水平分库和水平分表
        • 2、垂直分库和垂直分表
          • (1)垂直分库
          • (2)垂直分表
      • 四、分库分表的工具和步骤
        • 1、分库分表的工具---mycat
        • 2、分库分表步骤
      • 五、分库分表问题
        • 5.1、非partition key的查询问题
          • 5.1.1、端上除了partition key只有一个非partition key作为条件查询
          • 5.1.2、端上除了partition key不止一个非partition key作为条件查询
          • 5.1.3、后台除了partition key还有各种非partition key组合条件查询
        • 5.2、非partition key跨库跨表分页查询问题---ES
        • 5.3、扩容问题
      • 六、分库分表总结
      • 七、分库分表示例

一、数据库瓶颈

1、IO瓶颈—分库和垂直分表

第一种:磁盘读IO瓶颈,热点数据太多,数据库缓存放不下,每次查询时会产生大量的IO,降低查询速度 -> 分库和垂直分表

第二种:网络IO瓶颈,请求的数据太多,网络带宽不够 -> 分库

2、CPU瓶颈—SQL优化和水平分表

第一种:SQL问题,如SQL中包含join,group by,order by,非索引字段条件查询等,增加CPU运算的操作 -> SQL优化,建立合适的索引,在业务Service层进行业务计算。

第二种:单表数据量太大,查询时扫描的行太多,SQL效率低,CPU率先出现瓶颈 -> 水平分表

二、什么时候分库分表?

经测试在单表1000万条记录一下,写入读取性能是比较好的。再留点buffer,那么单表全是数据字型的保持在800万条记录以下, 有字符型的单表保持在500万以下。
如果按100库100表来规划,如用户业务:500万 x 100 x 100 = 5000000万 = 500亿记录。

三、分库分表

1、水平分库和水平分表

(1)划分:以字段为依据,按照一定策略(hash、range等),将一个库/表中的数据拆分到多个库/表中。
(2)使用场景:库多了,io和cpu的压力自然可以成倍缓解;单表数据量少了,单次SQL执行效率高,减轻了CPU的负担。

2、垂直分库和垂直分表

(1)垂直分库

划分:以表为依据,按照业务归属不同,将不同的表拆分到不同的库中。
使用场景:公用的配置表、字典表等越来越多,这时可以将这些表拆到单独的库中,甚至可以服务化。

(2)垂直分表

划分:以字段为依据,按照字段的活跃性,将表中字段拆到不同的表(主表和扩展表)中。
使用场景:将热点数据(可能会冗余经常一起查询的数据)放在一起作为主表,非热点数据放在一起作为扩展表。减少了随机读IO;注意分表后,要想获得全部数据就需要关联两个表来取数据,记住千万别用join,因为join不仅会增加CPU负担并且会讲两个表耦合在一起(必须在一个数据库实例上)。关联数据,应该在业务Service层做文章,分别获取主表和扩展表数据然后用关联字段关联得到全部数据。

四、分库分表的工具和步骤

1、分库分表的工具—mycat

sharding-sphere:jar,前身是sharding-jdbc;
TDDL:jar,Taobao Distribute Data Layer;
Mycat:中间件。

2、分库分表步骤

根据容量(当前容量和增长量)评估分库或分表个数 -> 选key(均匀)-> 分表规则(hash或range等)-> 执行(一般双写)-> 扩容问题(尽量减少数据的移动)。

五、分库分表问题

5.1、非partition key的查询问题

基于水平分库分表,拆分策略为常用的hash法

5.1.1、端上除了partition key只有一个非partition key作为条件查询

(1)映射法
(2)基因法
注:写入时,基因法生成user_id,如图。关于xbit基因,例如要分8张表,23=8,故x取3,即3bit基因。根据user_id查询时可直接取模路由到对应的分库或分表。根据user_name查询时,先通过user_name_code生成函数生成user_name_code再对其取模路由到对应的分库或分表。id生成常用snowflake算法。

5.1.2、端上除了partition key不止一个非partition key作为条件查询

映射法
冗余法
注:按照order_id或buyer_id查询时路由到db_o_buyer库中,按照seller_id查询时路由到db_o_seller库中。

5.1.3、后台除了partition key还有各种非partition key组合条件查询

NoSQL法
冗余法

5.2、非partition key跨库跨表分页查询问题—ES

基于水平分库分表,拆分策略为常用的hash法。解决方法是用NoSQL法解决(ES等)。

5.3、扩容问题

基于水平分库分表,拆分策略为常用的hash法。
水平扩容库(升级从库法),注:扩容是成倍的。

水平扩容表(双写迁移法)
第一步:(同步双写)修改应用配置和代码,加上双写,部署;第二步:(同步双写)将老库中的老数据复制到新库中;第三步:(同步双写)以老库为准校对新库中的老数据;第四步:(同步双写)修改应用配置和代码,去掉双写,部署;注:双写是通用方案。

六、分库分表总结

分库分表,首先得知道瓶颈在哪里,然后才能合理地拆分(分库还是分表?水平还是垂直?分几个?)。且不可为了分库分表而拆分。
选key很重要,既要考虑到拆分均匀,也要考虑到非partition key的查询。
只要能满足需求,拆分规则越简单越好。

七、分库分表示例

分库分表的git示例

转自:分库分表方案

你可能感兴趣的:(mysql)