从小白到架构师 | 数据库优化最后的杀手锏---数据库分片

你们公司的app经过大规模推广之后,用户数量急剧增加,系统产生的数据也呈现爆炸式增长。这种情况给数据库带来了瓶颈,进而使应用程序变慢,影响了用户体验。

数据库分片可以解决这个问题,然而,很多人对数据库分片的概念并不清楚,更重要的是,他们不知道在何种情况下应使用这种技术。

在本文中,我们将讨论什么是数据库分片,它是如何工作的以及使用它的最佳姿势。

在深入探索之前,有必要了解为什么我们要对数据存储进行分片,以及在分片之前还有哪些可行的选择—数据库分片成本很高,如果有其它更简单的方案能解决您系统的问题,尽量不使用数据库分片。

通常,当数据库中的表达到一定规模时,许多人会认为分片是解决所有问题的万能方案。然而,我曾遇到过一张包含数十亿条记录的表,并未使用分片技术却依然能正常工作。

什么是数据库分片?

简单来说,数据库分片是一种将数据分布到多台机器上的方法。当单台数据库实例无法处理预期的工作负载时,分片往往可以解决问题。

我们可以通过几种方式对数据进行分片,并将特定的表移至对应的数据库实例上。

一种方式称之为垂直分片(Vertical Sharding),它是根据表的列来分割数据。例如一个用户表,里面包含了很多列,比如 user_id、name、email、address、phone_number 等。当数据量很大时,这个表可能会变得很庞大,也难以管理。

在垂直分片中,我们可以将表拆分成多个子表,比如:

  • 一个表存储用户的基本信息:user_id、name、email
  • 另一个表存储用户的联系方式:user_id、address、phone_number

另一种方式是水平分片(Horizontal Sharding),它是根据表的行来分割数据。就是将同一张表的记录分别存储在多个数据库节点上,这引入了分片键的概念,我们会在后面详细介绍。

分片之前我有哪些选择?

在数据库分片之前,还有一些其他选择可以考虑。像任何分布式架构一样,数据库分片是有成本的。设置分片、保持每个分片上的数据更新、并确保请求被正确路由到对应的分片,这些都是非常耗时且复杂的操作。因此,在决定分片之前,您可能需要考虑是否有其他更简单的方案来解决系统中的问题。

选项 1:什么也不做。

如果系统目前没有明显的瓶颈或限制因素(例如硬件可以支持当前的工作负载),那么最好的选择可能是什么都不做。架构设计中有一个重要的原则——“不要过度设计”,这同样适用于此处。

选项 2:使用更合适的数据库

有时候,系统的性能问题可能是仅仅因为选择了不合适的数据库导致的。

举个例子,假设有一个电商网站,用户经常搜索产品。如果把所有搜索相关的数据都存储在 MySQL 这样的关系型数据库中,可能会导致查询速度变慢。这是因为关系型数据库不擅长处理大量的搜索请求。相反,如果把这些数据移到 Elasticsearch 这样的搜索引擎中,搜索性能会显著提高,因为 Elasticsearch 专门为搜索操作进行了优化。

类似地,如果你的网站需要存储大量的用户上传的图片或视频,把这些数据直接存储在 MySQL 中会占用大量的存储空间并且影响查询性能。把这些大块数据移到对象存储(如 AWS S3)中,可以减轻数据库的负担,提高整体性能。

选项 3:垂直扩展

垂直扩展是什么了?就是购买性能更强大(更强的CPU、更大的内容或磁盘)的服务器来部署数据库,这种方式不需要重新设计应用程序和数据库架构,相对数据库分片这种方案成本更低。

但是,垂直扩展也有两个不足之处:

  1. 存在上限:单台机器性能再怎么强大也是有上限的,即使是世界上最强大的服务器,也有可能在未来无法支撑您的业务需求。

  2. 单点故障:因为数据库实例只部署在一台机器上,一旦这台机器出问题了,意味着就不能为线上服务提供数据支持了,甚至导致数据的丢失,而数据可以说是一个企业最重要的资产之一。

选项 4:主从复制

如果您对数据库所做的大部分操作是读取数据,那么主从复制是一个不错的选择。

主从复制是一种常用的数据库分布式架构,用于提升系统的可用性和读写性能。它的基本原理是将主数据库服务器的写操作传播到一个或多个从数据库服务器,从数据库将这些写
操作也执行一遍以达到和主数据库数据一致的状态。

可以看出,主从复制实现了数据的冗余备份和读写分离。

必要时进行分片

如果前面介绍的几种方案还是搞不定了,那么可以考虑使用数据库分片了。

分片技术可以提高系统吞吐量、存储容量和可用性,从而为您提供几乎无限的可扩展性。

它是如何工作的?

在对数据库进行分片之前,我们需要回答几个重要问题。

1. 我们如何将数据分布到分片上?是否存在潜在的热点?

数据分布指的是如何根据某些规则将数据分配到不同的分片上。常见的分片方法有:

  • 按范围分片:根据某个字段的值范围进行分片,比如 user_id 在 1-1000 的数据放在分片1,1001-2000 的数据放在分片2。

  • 按哈希分片:对某个字段的值进行哈希运算,然后根据哈希值将数据分配到不同的分片。例如,将 user_id 进行哈希计算后,将结果对分片数量取模(求余),以决定数据放在哪个分片。

在分片过程中,热点问题指的是某个分片的数据量或访问量远远高于其他分片,导致该分片成为性能瓶颈,从而影响整个系统的效率。因此,设计分片策略时,需要尽量避免热点问题。

2. 我们会进行哪些查询,表之间如何交互?

假设我们有两个表:用户表(users)和订单表(orders)。用户表存储用户信息,订单表存储用户的订单信息。

我们可能经常进行如下查询:

# 查找某个用户的信息及其所有订单:这需要对用户表和订单表进行 JOIN 操作。
SELECT u.*, o.*
FROM users u
JOIN orders o ON u.user_id = o.user_id
WHERE u.user_id = 12345;


#查找某个用户的订单总数
SELECT COUNT(*) AS order_count
FROM orders
WHERE user_id = 12345;

在分片环境下,如果用户表和订单表的数据会分布在不同的物理服务器上,执行 JOIN 操作(如上述第一个查询语句),就必须跨越多个服务器去获取数据。这种跨服务器的查询通常效率较低。

因此,在设计分片策略时,需要考虑如何将相关数据放在同一个分片上,或使用某种机制来优化跨分片查询。

3. 数据如何增长?将来如何重新分布?

重新分布指的是在现有分片已经无法满足需求时,如何将数据重新分配到更多的分片上,以平衡负载并提高性能。

假设我们开始时有 3 个分片,分别存储不同范围的用户数据。随着用户数量增加,单个分片的数据量可能会超出物理服务器的处理能力,这时可能需要增加分片数量,比如从 3 个分片增加到 6 个分片。

重新分布数据时,可能需要将原本的分片的部分数据迁移到新的分片中,以确保系统的平稳运行。

分片相关的术语

理解以下术语对后续的学习很重要。

分片键

分片键是用于决定数据应该放在哪个分片的关键字段,选择合适的分片键非常重要(是从表中的字段选择),因为它直接影响到数据的分布和查询的性能。

例如有一个用户数据库,用户表中有字段 user_id 和 email。如果选择 user_id 作为分片键,那么数据将根据 user_id 的值来决定存储在哪个分片上。比如:

  • user_id 为 1 到 1000 的用户数据存在分片1
  • user_id 为 1001 到 2000 的用户数据存在分片2

这样,当你查询某个 user_id 的数据时,可以直接找到对应的分片,提高查询效率。

逻辑分片

逻辑分片是指将数据库中的数据根据分片键逻辑地划分为多个部分,每一部分称为一个逻辑分片。逻辑分片是数据在应用层面的分布,并不涉及实际的物理存储。

例如在用户数据库的例子中,假设有 6,000 个用户,我们可以将这些用户数据分成 6 个逻辑分片:

逻辑分片1:user_id 为 1 到 1000
逻辑分片2:user_id 为 1001 到 2000
以此类推,直到逻辑分片6
这些分片只是数据的逻辑分组,在应用层面用于管理和查找。

物理分片

物理分片是指将逻辑分片的数据实际存放在哪些物理位置上。每个物理分片可以包含一个或多个逻辑分片的数据。

假设有 3 个物理服务器(物理分片),我们可以将前面的 6 个逻辑分片分布到这 3 个物理服务器上:

  • 物理分片1:包含逻辑分片1, 2
  • 物理分片2:包含逻辑分片3 4
  • 物理分片3:包含逻辑分片5, 6

这样,当你查询某个 user_id 的数据时,应用程序首先通过分片键找到对应的逻辑分片,然后再定位到具体的物理分片进行查询。

常见的分片算法

哈希取模法

哈希函数是一种数学运算,它能将输入(即分片键)转换为一个固定范围内的数字(通常是整数)。然后用这个数字对分片数量取模,得到的值即代表将数据存放到哪个分片上。

哈希取模法通常能够将数据均匀分布到不同的分片中,这样每个分片的负载(即存储的数据量)就比较平衡,不容易出现某些分片过载的情况。

这种分片策略的缺点是,重新分片数据可能很困难,如果需要增加或减少分片数量(例如从 3 个分片增加到 5 个分片)将会涉及到将大量数据从旧分片迁移到新分片。

基于范围的分片

在基于范围的分片算法中,数据按照分片键字段的取值范围分布到不同的数据分片上,例如对于商品表,选定price作为分片键。

  • price为 10 到 149.99 的商品数据存在分片1
  • price 为 150 到 199.99 的商品数据存在分片2

注:在为这种分片算法选择分片键时,必须选择基数较高的分片键,这样该键的可能值数量就很多。例如,性别字段就不太适合作为分片键,因为该字段的基数较低,只有2 个(男或女)。

基于范围的分片算法很容易引起热点问题,例如订单数据库,以时间作为分片键,那么最近一段时间的订单肯定是访问最多的,但是它们又会被分布到同一个数据库分片上,这个分片就是个热点分片。

基于关系的分片

这种分片机制是将相关数据保存在同一个物理分片上。

我们以Instagram这样的应用为例,来说明这种分片策略的好处。在Instagram这样的应用中,一个用户和所有相关的数据,比如用户的帖子和评论,通常是紧密关联的。如果我们将这些相关数据放在同一个物理分片上,会有很多好处。

假设我们没有采用这种分片策略,同一用户的不同数据可能分布在不同的物理分片上,以用户123为例:

  • 用户123信息可能在分片1上。
  • 用户123的帖子在分片2上。
  • 用户123的评论在分片3上。

如果我们需要显示某个用户的所有帖子和评论,我们需要跨多个分片查询数据,这会增加查询的复杂性和时间。

如果采用了这种分片策略,将相关数据放在同一个物理分片上,还是以用户123为例,此时:

  • 用户123的信息在分片1上。
  • 用户123的所有帖子也在分片1上。
  • 用户123的所有评论也在分片1上。

当我们需要查询用户123的所有帖子和评论时,只需要访问分片1,就可以获取到所有相关数据,这样减少了跨分片查询的次数,提高了查询效率。

https://architecturenotes.co/p/database-sharding-explained

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值