认识分库分表

1 分库分表的背景

随着公司业务快速发展,数据库中的数据量增大,访问性能也变慢了,虽然通过机器集群,sql优化,性能调优等方式在一定程度上可以起到提高性能的作用,但是并不能从根本上解决单库,单表数据量过大的问题。分库分表就是为了解决由于数据量过大而导致数据库性能降低的问题,将原来独立的数据库拆分成若干数据库组成,将数据大表拆分成若干数据表组成,使得单一数据库、单一数据表的数据量变小,从而达到提升数据库性能的目的。

2 为什么要分库分表

2.1为什么要分库

降低磁盘存储: 业务发展迅猛,数据与日俱增,与此同时带来的MySQL单机磁盘容量倍增,进而影响数据库查询与使用。将单库拆成多个数据库,降低磁盘使用率,提升查询性能。
提高数据库可用性: 在高并发的用户请求下,会有大量的数据库请求,同时需要占用大量的数据库请求,导致连接数不够,请求处于阻塞状态。

2.2 为什要分表

提高查询速度: 随着业务发展,单表数据量越来越多,导致在查询的时候非常慢,影响查询效率。
提高读写性能: 当数据量增长到一定程度后,数据表查询就会越来越慢,如果需要增加字段就非常麻烦,mysql增加字段时会出现锁表。此时数据库所有读写操作只能等待,包括重建索引效率也很低。

3 什么时候分库

业务发展很快,还是多个服务共享一个单体数据库,数据库成为了性能瓶颈,就需要考虑分库了。比如订单、用户等,都可以抽取出来,新搞个应用(其实就是微服务思想),并且拆分数据库(订单库、用户库)

4 什么时候分表

如果你的系统处于快速发展时期,如果每天的订单流水都新增几十万,并且,订单表的查询效率明变慢时,就需要规划分库分表了。一般B+树索引高度是2~3层最佳,如果数据量千万级别,可能高度就变4层了,数据量就会明显变慢了,一般500万数据就要考虑分表了

5 如何分库分表

在这里插入图片描述
分库分表的核心理念就是对数据进行切分(sharding),以及切分后如何对数据的快速定位与查询结果整合。而分库与分表都可以从:垂直(纵向)和 水平(横向)两种纬度进行切分:

5.1 垂直拆分

5.1.1 垂直分库

在这里插入图片描述

概念: 以表为依据,按照业务归属不同,将不同的表拆分到不同的库中

结果:

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

垂直分库,将原来一个单数据库的压力分担到不同的数据库,可以很好应对高并发场景。数据库垂直拆分后的架构如下:
在这里插入图片描述

5.1.2 垂直分表

如果一个单表包含了几十列甚至上百列,管理起来很混乱,每次都select * 的话,还占用IO资源。这时候,我们可以将一些不常用的、数据较大或者长度较长的列拆分到另外一张表。

比如一张用户表,它包含user_id、user_name、mobile_no、age、email、nickname、address、user_desc,如果email、address、user_desc等字段不常用,我们可以把它拆分到另外一张表,命名为用户详细信息表。这就是垂直分表:
在这里插入图片描述

5.2 水平拆分

5.2.1 水平分库

将表的数据量切分到不同的数据库服务器上,每个服务器具有相同的库和表,只是表中的数据集合不一样。它可以有效的缓解单机单库的性能瓶颈和压力
用户库的水平拆分架构如下:
在这里插入图片描述

5.2.2 水平分表

如果一个表的数据量太大,可以按照某种规则(如hash取模、range),把数据切分到多张表去。
一张订单表,按时间range拆分如下:
在这里插入图片描述

5.3 垂直拆分VS水平拆分

优点缺点
垂直拆分1、解决业务系统层面的耦合,业务清晰;
2、与微服务的治理类似,也能对不同业务的数据进行分级管理、维护、监控、扩展等;
3、高并发场景下,垂直切分一定程度的提升IO、数据库连接数、单机硬件资源的瓶颈;
1、部分表无法join,只能通过接口聚合方式解决,提升了开发的复杂度。
2、分布式事务处理复杂;
3、依然存在单表数据了过大的问题(需要水平切分)
水平拆分1、不存在单库数据量过大、高并发的性能瓶颈,提升系统稳定性和负载能力;
2、应用端改造较小,不需要拆分业务模块;
1、跨分片的事务一致性难以保证;
2、垮库的join关联查询性能较差;
3、数据多次扩展难度和维护量极大;
4、水平切分后同一张表会出现在多个数据库/表中,每个库/表的内容不同;

5.4 水平分库分表策略

分库分表策略一般有几种,使用与不同的场景:
range范围
hash取模
range+hash取模混合

5.4.1、range范围

range,即范围策略划分表。比如我们可以将表的主键,按照从0 ~ 1000万的划分为一个表,1000 ~ 2000万划分到另外一个表。如下图:
在这里插入图片描述

优点:

  • 这种方案有利于扩容,不需要数据迁移。假设数据量增加到5千万,我们只需要水平增加一张表就可以,之前0~4000万的数据,不需要迁移。

缺点:

  • 这种方案会有热点问题,因为订单id是一直在增大的,也就是说最近一段时间都是汇聚在一张表里面的。比如最近一个月的订单都在1000万~2000万之间,平时用户一般都查最近一个月的订单比较多,请求都打到order_1表,这就导致数据热点问题。

5.4.2、hash取模

hash取模策略:指定的路由key(一般是user_id、订单id作为key)对分表总数进行取模,把数据分散到各个表中。
比如原始订单表信息,我们把它分成4张分表:
在这里插入图片描述

优点:

  • hash取模的方式,不会存在明显的热点问题。

缺点:

  • 如果一开始按照hash取模分成4个表了,未来某个时候,表数据量又到瓶颈了,需要扩容,这就比较棘手了。比如你从4张表,又扩容成8张表,那之前id=5的数据是在(5%4=1,即t_order_1),现在应该放到(5%8=5,即t_order_5),也就是说历史数据要做迁移了。

5.4.3、range+hash取模混合

既然range存在热点数据问题,hash取模扩容迁移数据比较困难,我们可以综合两种方案一起嘛,取之之长,弃之之短。

比较简单的做法就是,在拆分库的时候,我们可以先用range范围方案,比如订单id在0 ~ 4000万的区间,划分为订单库1;id在4000万 ~ 8000万的数据,划分到订单库2,将来要扩容时,id在8000万~1.2亿的数据,划分到订单库3。然后订单库内,再用hash取模的策略,把不同订单划分到不同的表
在这里插入图片描述

6 分库分表中间件

目前流行的分库分表中间件比较多:

  • cobar
  • Mycat
  • Sharding-JDBC
  • Atlas
  • TDDL(淘宝)
  • vitess
    在这里插入图片描述

7 总结

  1. 分库分表,首先需要知道数据库瓶颈在哪里,然后才能合理地拆分。且不可为了分库分表而拆分,否则效率会适得其反。选key很重要,既要考虑到拆分均匀,也要考虑到非partition key的查询。只能能够满足需求,拆分规则越简单越好。
  2. 分库分表如何动态扩容:准备好数据库服务器,每台服务器上几个库,每个库多少个表,推荐是32库 * 32表。路由规则,key%32 = 库,key/32%32 = 表。扩容的时候,申请增加新增的数据库服务器,装好mysql,倍数扩容。将原先数据库服务器的库,迁移到新的数据库服务器上去。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

摆烂的小趴菜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值