关于数据库分库分表方案

一、数据库瓶颈

  1. IO瓶颈
  2. CPU瓶颈

二、分库分表

  1. 水平分表
  2. 水平分库
  3. 垂直分表
  4. 垂直分库

三、分库分表工具

四、分库分表步骤

五、分库分表问题

  1. 非partition key的查询问题(水平分库分表,拆分策略为常用的hash法)
  2. 非partition key跨库跨表分页查询问题(水平分库分表,拆分策略为常用的hash法)
  3. 扩容问题(水平分库分表,拆分策略为常用的hash法)

六、分库分表总结

七、分库分表示


一 、 数据库瓶颈

不管是IO瓶颈,还是CPU瓶颈,最终都会导致数据库的活跃链接数增加,今儿逼近甚至达到数据库可承载活跃连接数的阈值。在业务Service来看就是 可用数据库连接少甚至无连接可用。接下来就是(并发量、吞吐量、崩溃)

1、IO瓶颈

第一种:磁盘读IO瓶颈,热点数据太多了,数据库缓存放不下,每次查询时会产生大量的IO,降低查询速度 — 分库和垂直分表
第二种:网络IO瓶颈,请求的数据太多了,网络带宽不够 — 分库

2、CPU瓶颈

第一种:SQL问题,如SQL中包含join、group by、order by,非索引字段条件查询等,增加CPU运算的操作 — SQL优化、建立合适的索引、在Service层进行业务计算
第二种:单表数据量太大,查询时扫描的行太多,SQL效率低,CPU率出现瓶颈 — 水平分表

二 、分库分表

1、水平分库

在这里插入图片描述
1、概念:以字段为一句,按照一定的策略(hash、range等),将一个库中的数据拆分到多个库中。

2、结果:

  • 每个库的结构都一样;
  • 每个库的数据都不一样,没有交集;
  • 所有库的并集是全量数据

3、场景:系统绝对并发量上来了,分表难以从根本上解决问题,并且还没有明显的业务归属来垂直分库。

4、分析:库多了以后IO和CPU的压力可以成倍的得到缓解。

2、水平分表

在这里插入图片描述
1、概念:以字段为一句,按照一定的策略(hash、range等),将一个表中的数据拆分到多个表中。

2、结果:

  • 每个表的结构都一样;
  • 每个表的数据都不一样,没有交集;
  • 所有表的并集是全量数据;

3、场景:系统绝对并发量没有上来,只是单表的数据量太多,影响了SQL效率,加重了CPU负担,以至于成为了瓶颈。

4、分析:表的数据量少了,单次SQL执行效率高,自然减轻了CPU负担。

3、垂直分表

在这里插入图片描述
1、概念:以表为依据,按照业务的归属不同,将不同的表拆分到不同的库中。

2、结果:

  • 每个库的结构都不一样;
  • 每个库的数据也不一样,没有交集;
  • 所有库的并集是全量数据;

3、场景:系统绝对并发量上来了,并且可以抽象出单独的业务模块。

4、分析:到这一步,基本上就可以服务化了。例如,随着业务的发展一些公用的配置表、字典表等越来越多,这是可以将这些表拆到单独的表中甚至可以服务化。再有随着业务的发展孵化出一套业务模式,这是可以将相关的表拆到单独的库中,甚至服务化。

4、垂直分表

在这里插入图片描述
1、概念:以字段为依据,按照字段的活跃性,将表中的字段拆到不同的表(主表和扩展表)中。

2、结果:

  • 每个表的结构都不一样;
  • 每个表的数据也不一样,一般来说,每个表的字段至少有一列交集,一般是主键,用于关联数据;
  • 所有表的并集是全量数据;

3、场景:系统绝对并发量并没有上来,表的纪录并不多,但是自短多,并且热点数据和非热点数据在一起,单行数据所需的存储空间比较大,以至于数据库缓存的数据行减少,查询的时候去读磁盘数据产生大量的随机读IO,产生IO瓶颈。

4、分析:可以用列表页和详情页来帮助理解。垂直分表的拆分原则是将热点数据(可能会冗余经常一起查询的数据)放在一起作为主表,非热点数据放在一起作为扩展表。这样更多的热点数据就能被缓存下来,进而减少了随机读IO。查了以后要想获得全部数据就需要关联两个表来读取数据,但是要记住,千万千万别用join,因为join不仅会增加CPU负担并且会将两个表偶合在一起(必须在一个数据库实例上)。关联数据应该在业务Service层做文章,分别获取主表和扩展表然后关联字段,得到全部数据。

三、分库分表工具

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

PS:具体使用哪个工具,请自行决定,依据官网和相应社区。

四、分库分表步骤

  1. 根据容量(当前容量和增长量)评估分库或者分表个数
  2. 选key(均匀选取)
  3. 分表规则(hash或者range等)
  4. 执行(一般双写)
  5. 扩容问题(尽量减少数据的移动)

五、分库分表问题

1、非partition key的查询问题(水平分库分表常用hash法)

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

  • 映射法
    在这里插入图片描述
  • 基因法
    在这里插入图片描述
    注:写入时,基因法生成user_id,如图。关于xbit基因,例如要分8张表,23=8,故x取3,即3bit基因。根据user_id查询时可直接取模路由到对应的分库或分表。根据user_name查询时,先通过user_name_code生成函数生成user_name_code再对其取模路由到对应的分库或分表。id生成常用snowflake算法
    2、端上除了partition key不止一个非partition key作为条件查询
  • 映射法
    在这里插入图片描述
  • 冗余法
    在这里插入图片描述
    按照order_id或者buyer_id查询时路由到db_o_buyer库中,按照seller_id查询时路由db_o_seller库中。不知道改变技术栈会不会有用?

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

  • NoSQL法
    在这里插入图片描述
  • 冗余法在这里插入图片描述

2、非partition key跨库跨表分页查询问题(水平分库分表,拆分策略为常用的hash法)

用NoSQL法解决(ES等)

3、扩容问题(水平分库分表,拆分策略为常用的hash法)

1、水平扩容库(升级从库法)
在这里插入图片描述
注:扩容是成倍的

2、水平扩容表(双写迁移法)
在这里插入图片描述
第一步:(同步双写)应用配置双写,部署;
第二步:(同步双写)将老库中的老数据复制到新库中;
第三步:(同步双写)以老库为准校对新库中的老数据;
第四步:(同步双写)应用去掉双写,部署

注:双写是通用方案

六、分库分表总结

分库分表首先得知道瓶颈在哪里,然后才能合理的拆分–分库还是分表?水平还是垂直?分几个?还应该注意的一点就是不能为了分库分表而拆分

1、选key很重要,既要考虑到拆分均匀,也要考虑到非partition key的查询
2、只要能满足需求,拆分规则越简单越好

七、分库分表示例

示例GitHub地址:https://github.com/littlecharacter4s/study-sharding

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值