【科普】谈谈分库分表与分片

一. 大纲

在谈论数据库架构和数据库优化的时候,我们经常会听到分库分表分区分片(Sharding)等关键词,对于这些概念,相信大家应该都有听说过或是浏览过相关的文档,我们今天就来详细了解下这几个比较容易混淆的概念。

首先呢,我们需要知道上述的这些方案都是为了同一个目的而产生,那就是为了突破单表/库过大单节点数据库服务器的性能瓶颈,解决数据库的扩展性问题。

因为随着表数据量的增长,单机数据库的资源和处理能力有限,所以数据库非常容易成为应用系统的瓶颈。

二. 分库

垂直分库微服务盛行的今天已经非常普及了,基本的思路就是按照业务模块来划分出不同的数据库,而不是像早期一样将所有的数据表都放到同一个数据库中。

系统层面的服务化拆分能够解决业务系统层面的耦合性能瓶颈,有利于系统的扩展维护。

而数据库层面的数据拆分,道理其实也是相通的,可以更加便于数据库的管理、维护、监控、扩展等。

垂直分库可以在一定程度上解决数据库单机瓶颈,因为可以将不同的业务库分散在不同的服务器上,独享资源,互不干扰,但是一定要了解清楚拆分的原则与技巧,否则会遇到很多问题,例如:跨库JOIN分布式事务等。

三. 分表

分表就是将一张大表拆分成N个子表,根据切分规则,通常由如下两种模式:

  • 垂直拆分:基于拆分表,将表中的某些字段拆分出去放入到扩展表中。

  • 水平拆分:基于拆分表,通过规则匹配分类后,将数据放到若干个子表中。

3.1. 垂直分表

垂直分表在日常开发和设计中比较常见,通俗的说法叫做大表拆小表,拆分是基于关系型数据库中的列(字段)进行的。

通常情况下,当某个表中的字段比较多时,可以新建一张扩展表,将不经常使用或者长度较大的字段拆分出去。

垂直分表的作用比较有限,它只可以减少行数据大小,加快数据检索的速度,但是无法解决因为表数据量增长而导致的压力。

表字段拆分(垂直分表)建议在数据库设计阶段就做好,如果是在发展过程中拆分,则需要改写以前的查询语句,会额外带来一定的成本和风险。

3.2. 水平分表

水平分表也称为横向分表,就是将表中不同的数据行按照一定规律分布到不同的数据库表中(这些表保存在同一个数据库中),以此来降低单表数据量,优化查询性能。

这种同库下水平分表通常有以下几张方式:

  1. 冷热数据分离:

    • 定期将使用较少的历史数据迁移到对应的历史表中,减少原表的数据量。

  2. 业务分表:

    • 在代码层面实现分表,数据库中存在多张子表,但在应用上层表现为一张表。

  3. 分区表:

    • 通过数据库自带的分区表功能实现分表,逻辑上表现为一张表,但是底层存储在不同的分区上。



水平分表能够降低单表的数据量(分区表必须要带上分区条件才可以提前过滤),一定程度上缓解查询性能瓶颈。但本质上这些表还是保存在同一个库,或者说同一个数据库实例、同一个DB服务器中,所以无法避免单机数据库性能瓶颈的问题。

四. 分片

分片也叫做Sharding,或是水平分库分表,都是相同的概念,与上面所讲到的水平分表的概念类似,唯一不同点就在于将这些拆分出来的子表保存在不同的数据库服务器中。



常见分片策略

  1. RANGE:按照范围划分,比如按照日期或者自增键进行范围划分。

  1. HASH: 采用 hash+mod 的组合划分数据。

分片实现方式

  1. 客户端:

    • 在客户端实现分片,如比较流行的分库分表框架Sharding-JDBC,就是在驱动层实现了分片功能,对上层应用保持透明。

  2. 中间层:

    • 通过在应用与DB之间接入中间件(Proxy),如DBLE、MaxScale等开源中间件,用于实现后端数据分片与路由查询,对上层应用保持透明。

  3. 服务端:

    • 使用某些分布式数据库,如TiDB、SequoiaDB等开源NewSQL,其在存储引擎层实现了数据分片功能,对上层应用保持透明。

分片能够有效的缓解单机、单库、单表的性能瓶颈,突破IO、连接数、硬件资源等瓶颈。但是我们一旦将数据分片后,那么整个数据库架构就转换成了分布式架构,也会引发诸多问题:

  1. 分布式事务:

    • 数据分片后,原先的本地事务就演变成了分布式事务了,一般需要通过二阶段或三阶段提交来保证分布式事务的ACID特性,性能也因此会有一定损耗。

     

  2. 跨库join:

    • 分库分表后,不同的表分布在不同的服务器上,所以无法直接通过sql join来进行查询,这时候通常会建立冗余字段全局表来实现跨库join。

     

  3. SQL问题:

    • 数据分片后,SQL的运行需要分发到各个节点计算,然后将结果合并后再返回,性能会有所下降,并且当SQL较为复杂时,结果准确性也有可能出现问题。这个问题也是数据分片实现中最为关键的点,只能不断优化完善,无法完全解决。

     

  4. 自增主键:

    • 数据分片后,我们将不能再依赖数据库自身的自增键生成机制,需要配置额外的全局序列来保证自增主键的全局唯一。

五. 小结

需要注意的是,分片(Sharding)会为数据库维护和业务逻辑带来一系列复杂性和性能损耗,所以除非业务量大到万不得已,否则切莫过度设计过早优化

面对数据库性能问题,我们可以先尝试用以下方式来解决:

  1. 数据优化:优化SQL、索引及相关数据库参数配置。

  2. 硬件扩展:提升服务器CPU、内存、磁盘IOPS等硬件配置。

  3. 读写分离:通过读写分离架构提高数据库的整体性能。

  4. 数据拆分:通过垂直拆分库表,或水平分表来解决大表性能问题

如果上述方式仍未能奏效,才考虑最复杂的方案:数据分片

posted @ 2021-06-25 16:08  时光与我恰经过  阅读(2219)  评论(0编辑  收藏  举报