一、分库分表介绍

1、分库分表简介

  为什么要用分库分表,是因为随着公司业务快速发展,数据库中的数据量猛增,访问性能也变慢了,优化迫在眉睫。分析一下问题出现在哪?
  关系型数据库本身比较容易成为系统瓶颈,单机存储容量、连接数、处理能力都有限。当档表的数据量达到1000w或100g以后,由于查询维度较多,即使添加从库、优化索引,做很多操作时性能扔下降严重。
  方案一:
  通过提升服务器硬件能力来提高数据处理能力,比如增加存储容器、CPU等,这种方案成本很高,并且如果瓶颈在MySQL本身那么提高硬件也是很有限的。
  方案二:
  把数据分散在不同的数据库中,使得单一数据库的数据量变小来缓解单一数据库的性能问题,从而达到能提升数据库性能的目的,如下图:将电商数据库拆分为若干独立的数据库,并且对于大表也拆分为若干小表,通过这种数据库拆分的方法来解决数据库的性能问题。在这里插入图片描述
  分库分表就是为了解决由于数据量过大而导致数据库性能降低的问题,将原来独立的数据库拆分为若干数据库,将大数据表拆分为若干数据表,使得单一数据库、单一数据表的数据量变小,从而达到提升数据库性能的目的。

2 分库分表的方式

  分库分表包括分库和分表两部分,在生产中通常包括:垂直分库、水平分库、垂直分表、水平分表四种方式。

2.1 垂直分表

  以一张商品信息表为例,用户在浏览商品列表时,只有对某商品感兴趣时才会查看该商品的详细描述,因此,商品信息中商品描述字段访问频次较低,且该字段存储占用空间较大,访问单个数据 IO 时间较长;而商品信息中商品名称、商品图片、商品价格等其他字段数据访问平次较高。
  由于这两种数据的特性不一样,因此考虑将商品信息进行拆分,将访问频次低的商品描述信息单独存放在一张表中,访问频次较高的商品基本信息单独放在另一张表中,这叫垂直分表,如下图所示:
在这里插入图片描述
  为什么这样分?放在一张表中不行吗?分了之后写 sql 还需多表联查,之前的一条 sql 就搞定了
  熟悉淘宝之类的购物网站都知道,在商品列表中,都是商品的基本信息,而当看中某件商品之后才会点进去查看详细信息。
  有人觉得是这样没错,但是和之前的有什么分别呢?
  这就得从关系型数据库的存储开始理解。

  • 第一,大字段的 IO 效率低,数据量本身较大,需要更多的读取时间
  • 第二,数据库存储的单位是页,很多查找及定位操作doushi以页为单位,单页内的数据行越多,数据库整体性能就越好。而大字段占用空间大,单页内存储行数就变少,因此效率低
  • 第三,数据库以行为单位将数据加载到内存中,这样表中字段长度较短且访问频次较高,内存能加载到更多的数据,命中率更高,减少磁盘 IO,从而提高数据库性能。
      因此,我们通常按以下原则进行垂直拆分
  • 把不常用的字段单独放在一张表
  • 把 text,blob 等大字段拆分出来放在附表中
  • 经常组合查询的列放在一张表中
2.2 垂直分库

  通过垂直分表性能得到了一定程度的提升,但是还没有达到要求,并且磁盘空间也快不够了,因为数据还是始终限制在一台服务器,库内垂直分表只能解决了单一表数据量过大的问题,但是没有将表分布到不同的服务器上,因此每个表还是竞争同一个物理机的 CPU、内存、网络 IO、磁盘。
  比如,当前有 1 个电商数据库,库中有商品基本信息表、商品详细信息表、店铺表、地域区域表等。由于商品信息和商品描述业务耦合度较高,我们可以将商品归在一个一台物理机的数据库中,而店铺信息相对独立,因此将店铺表归为另一台物理机的数据库中。这就是垂直分库
  垂直分库是指按照业务将表进行分类,分布到不同的数据库上面,每个库可以放在不同的服务器上,它的核心理念是专库专用。

  优点

  • 解决业务层面的欧欧赫,业务清晰
  • 能对不同业务的数据进行分级管理、维护、监控、扩展等
  • 高并发场景下,垂直分库一定程度的提升 IO、数据库连接数、降低单机硬件资源的瓶颈

  垂直分库通过将表按照业务分类,然后分布在不同数据库中,并且可以将这些数据库部署在不同的服务器上,从而达到多个服务器共同分摊压力的效果,但是依然没有解决单表数据量过大的问题。

2.3 水平分库

  经过垂直分库后,数据库性能问题得到一定程度的解决,但是随着业务量的增长,商品库单库存储数据已经超过预估。粗略估计,目前有 8w 店铺,每个店铺平均 150 个不同规格的商品,再算上增长,那商品数量得往 1500w+ 上预估,并且商品库属于访问非常频繁的资源,单台服务器已经无法支撑。此时该如何优化?
  再次分库?但是从业务角度分析,目前情况已经无法再次垂直分库。
  尝试水平分库,将店铺 ID 为单数的和店铺 ID 为双数的商品信息分别放在两个库中。
  也就是说,要操作某条数据,先分析这条数据所属的店铺 ID。如果店铺 ID 为双数,将此操作印射至双数的商品库;反之则印射到单数的商品库。这叫水平分库
  水平分库是把同一个表的数据按一定规则拆分到不同的数据库中,每个库可以放在不同的服务器上。

对比垂直分库:垂直分库是把不同表拆到不同数据库中,它是对数据行的拆分,不影响表结构

  优点

  • 解决了单库大数据,高并发的性能瓶颈
  • 提高了系统的稳定性及可用性

稳定性体现在 IO 冲突减少,锁也减少,可用性指某个库出问题,部分可用。

  当一个应用难以再细粒度的垂直切分,或切分后数据量行数巨大,存在单库读写、存储性能瓶颈,这时候就需要进行水平分库了,经过水平切分的优化,往往能解决单库存储量及性能瓶颈。但由于同一个表被分配在不同的数据库,需要额外进行数据操作的路由工作,因此大大提升了系统复杂度。

2.4 水平分表

  水平分表其目的也是为了解决单表数据量大的问题。本来水平分库就可以解决了数据单表数据量过大的问题,为啥还要进行水平分表呢?
  在水平分库中,如果继续按照其他规则分下去,会不断得增加服务器数量,对运维的成分是相当的高。因此需要水平分表。
  水平分表与水平分库的思路类似,不过这次操作的目标是表,商品信息及商品描述被分为两套表。如果商品 ID 为双数,将此操作映射到双数的商品信息表,反之则插入单数的商品信息表。这就是水平分表
  水平分表是在同一个数据库内,把同一张表的数据按照一定规则拆到多个表中。

对数据行的拆分,不影响表结构

  优点

  • 优化单一表数据量过大而产生的性能问题
  • 避免 IO 争抢并减少锁表的几率

  库内的水平分表,解决了单一表数据量过大的问题,分出来的小表中只含有一部分数据,从而使得单个表的数据量变小,提高检索性能。

3 分库分表带来的问题

  分库分表能有效的缓解了单机和单库带来的性能瓶颈和压力,突破网络 IO、硬件资源、连接数的瓶颈,同时也带来了一些问题。

3.1 事务一致性问题

  由于分库分表把数据分布在不同库甚至不同服务器,不可避免会带来分布式事务问题。

3.2 跨节点关联查询

  在没有分库之前,我们检索商品时可以通过以下 SQL 对店铺信息进行关联查询,

Select p.*,r.[地理区域名称], s.[店铺名称], s.[信誉] from shop 
Left join [地理区域] r on p.[产地] = r.[地理区域编码]
Left join [店铺信息] s on p.id = s.[所属店铺]
where ... order by ...limit ..

  但垂直分库之后【商品信息】和【店铺信息】不在一个数据库,甚至不在一台服务器,无法进行关联查询。
  可将原关联查询分为两次查询,第一次查询的结果集中找出关联数据 id,然后根据 id 发起第二次请求得到关联数据,最后将得到的数据进行拼装。

3.3 跨节点分页、排序函数

  跨节点多库进行查询时,limit 分页、order by 排序等问题,就变得比较复杂了。需要先在不同的分片节点中将数据进行排序并返回,然后将不同分片返回的结果集进行汇总和再次排序。
  如,进行水平分库后的商品库,按 ID 排序分页,取第一页:

在这里插入图片描述
  以上流程是第一页的数据,性能影响不大,但由于商品信息的分布在各数据库的数据可能是随机的,如果是取第 N 页,需要将所有节点前 N 页数据都取出来合并,再进行整体的排序,操作效率可想而知,所以请求页数越大,系统的性能也会越差。
  在使用 Max、Min、Sum、Count 之类的函数进行计算的时候,与排序分页同理,也需要先在每个分片上执行相应的函数,然后将各个分片的结果集进行汇总和再次计算,最终将结果返回。

3.4 主键避重

  在分库分表环境中,有偶遇表中数据同时存在不同数据库中,主键值平时的自增长将无用武之地,某个分区数据库生成的 ID 无法保证全局唯一。因此需要单独设计全局主键,以避免跨库主键重复问题。

在这里插入图片描述

3.5 公共表

  实际的应用场景中,参数表、数据字典表等都是数据量较小,变动少,而且数据高频联合查询的依赖表。例子中地理区域表也属于此类型。
  可以将这类表在每个数据库都保存一份,所有对公共表的更新操作都同时发动到所有分库执行。
  由于分库分表之后,数据被分散在不同的数据库、服务器。因此,对数据的操作也就无法通过常规方式完成,并且它还带来了一系列的问题。好在,这些问题不是所有都需要我们在应用层面上解决,市面上有很多中间件可供我们选择,其中 Sharding-JDBC 使用流行度较高,接下来的章节来了解一下它。

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值