数据库分片详解 - 2021 数据库扩展教程

2025-05-26

数据库分片详解 - 2021 数据库扩展教程

如果您想充分发挥作为开发人员的潜力,您至少需要对应用程序各个级别的工作方式有基本的了解。

对于工程师来说,更高级别的职位更看重的是系统设计能力,而不是纯粹的编程能力。如果你想在职业发展中取得进步,掌握这些技能至关重要。

在这篇文章中,我将深入介绍数据库分片,以及一些与数据库扩展相关的其他基本概念。

文章摘要:

  • 什么是数据库分片
  • 为什么要使用数据库分片
  • 分片的优缺点
  • 数据库分片与数据库分区
  • 数据库分片架构
  • 什么原因导致数据库速度变慢?
  • 数据库分片替代方案

完整数据库扩展视频

如果您更喜欢观看视频,并且还想了解有关扩展数据库(不仅仅是分片)的更多信息,请观看以下视频:

什么是数据库分片

简单来说,这意味着你将数据拆分成“分片”,不同的部分组合在一起,共同保存所有数据。这使得应用程序的扩展能力远远超出单个传统数据库的限制。

您的数据库陷入困境

用人的话来说,想象一下拥有一家成功的面包店。最终,你发现自己无法独自处理太多工作,于是雇佣员工来制作饼干、蛋糕和布朗尼。你把工作分担了,这样你的公司就能完成比你独自一人更多的事情。

为什么要使用数据库分片

数据库分片主要有两个原因:复制和处理大量数据。

复制


分片技术允许复制,因为我们可以将每个数据分片复制到多台服务器上,从而提高应用程序的可靠性。如果其中一台服务器宕机,我们仍然有其他服务器可以处理请求。使用分片数据库,您的应用程序将不再存在单点故障,容错能力更强。

大数据需要分片,原因很简单:规模庞大时,单台机器无法容纳全部数据集。想象一下,Facebook 试图将数 PB 的数据存储在一台服务器上的单个数据库中?这根本不可能。在海量数据下,必须将数据分片成易于管理的部分,然后分布到大量服务器上。

分片的好处

水平分片图

可扩展性

如果不进行分片,提升数据库性能的唯一选择就是垂直扩展。这意味着在单台机器上添加更多磁盘空间、内存和更快的 CPU,以应对应用程序日益增长的数据量。

通过分片,您可以将数据分成大小相等、易于管理的块,这些块可以分布在多个可以轻松扩展的廉价商品服务器上。

弹性

拥有所有这些小型服务器的副作用意味着您的应用能够更好地应对故障。您可以将每个分片存储在多个服务器/节点上。

这意味着即使一台服务器发生故障,您的应用仍然可以检索所需的数据。如果您依赖于一台大型数据库服务器,一旦它宕机,麻烦就大了。

提高性能

由于数据被分解成更小的部分,查询只需搜索较少的数据。这加快了数据库性能并缩短了响应时间。

您还可以选择将这些分片分布在世界各地的多个数据中心,这意味着减少延迟并为您的用户提供更好的整体体验。

分片的缺点

替代文本

复杂

分片是有代价的,那就是处理分散在所有服务器上的数据会增加额外的复杂性。在扩展数据库时,分片应该始终是最后的手段,其他替代方案(例如只读副本和缓存)应该优先实现,因为它们更容易实现。

当你确实需要对数据库进行分片时,你的目标应该是将其从应用程序开发人员中抽象出来。对于你的工程师来说,他们应该像往常一样只是写入数据库,而在后台,服务或库应该承担起确保数据分发到正确分片的重任。

一些数据库具有内置的分片支持并在应用程序层之外处理这个问题,这降低了团队的复杂性。

数据一致性

保持跨节点数据一致性是分片带来的额外复杂性的一个例子。现在,您还需要考虑诸如数据更新时如何更新特定分片的所有节点之类的问题。

在某些情况下,如果某些内容被更新,但这些更改并未传播到向其他用户提供数据的所有分片,那么您最终可能会向用户提供过时的数据。

数据库分片的类型

在对数据库进行分片时,最重要的决策之一就是如何划分数据。目标应该是将负载均匀地分布在所有分片上。

例如,根据用户 ID 将数据库分片为大小相等的块听起来非常聪明,是一个理想的解决方案。

然而,你可能会遇到与 Instagram 类似的问题,Justin Bieber 的账户流量远高于普通账户。这导致该特定数据库分片持续超载,尽管其分区的用户账户总数相同。Justin Beiber 每次发帖,整个 Instagram 应用的全球用户访问速度都会变慢。

这个问题在数据库中被称为“热点”或“热键”。选择数据库分片方式的目标是防止热点等问题影响应用程序性能。

数据库分片架构

数据库分片有多种不同的方法。本节我将介绍几种最常见的策略。

基于密钥的分片

基于键的分片的工作原理是,从新提交的数据中获取一个值,并对其进行哈希函数运算。该哈希函数决定了数据将被写入哪个特定的分片。从所选数据中获取的值称为分片键。

该策略的缺点是,当添加或删除服务器时,需要将数据重新映射到哈希值。

基于范围的分片

基于范围的分片是指根据写入值的定义范围对数据进行分片。以下是一些示例:

  • 价格低于 10 美元的商品和高于 10 美元的商品会被放入不同的分片中
  • 每周提交的项目都会被放入一个分片中

这种分片方式直观且易于实现,但容易导致热点和数据分布不平衡。

查找服务分片

目录大脑
此分片策略的工作原理是,在分片数据库前面实现一个查找表。该服务跟踪当前的分区方案,并映射到每个分片的位置。

这样做的好处是,底层分片方案可以在不影响应用程序代码的情况下进行更改。缺点是查找服务可能成为故障点。

数据库分片与数据库分区

在谈论数据库时,“分片”和“分区”这两个术语经常被提及。对我来说,这是学习这些知识时最令人困惑的方面之一,因为它们经常互换使用,而且这两个术语之间有一定程度的重叠。

在本节中,我将尝试消除一些困惑,并让您免于在网上搜索答案的痛苦。

分区是将单个数据集分成多个部分的总称。

从技术上讲,数据库分片是数据库分区的一个子集,具体来说是对数据进行水平分区。分片实际上是创建当前数据库列模式的副本,然后将其除以您决定使用的分片键数量。

垂直分区是指按列拆分数据库表。例如,可以将单个用户数据表拆分为多个不同的表,例如个人信息表和地址/位置数据表。

水平分片

可视化水平分片非常简单。想象一下,有一个包含大量行和一定数量列的 Excel 电子表格。

要水平分片此 Excel 电子表格,只需选择一列作为分片键,然后选择要创建的键数即可。在本例中,我们选择“name”列作为分片键。

水平分区或分片

您可以通过创建两个分片(分别名为 AM 和 NZ)将数据一分为二。如果数据量过大,两个分片不够用,您可以将其分成 26 个分片,每个字母一个。

在生产环境中,仅根据首字母进行分片可能被认为是一种简单的实现,但核心概念是一样的。你选择一列数据进行分片,然后选择如何对该数据进行分组。

垂直分片/分区

垂直分片是指按列而不是按行拆分数据。这种方法不太常用,但在某些情况下非常有用。

垂直隔断

Instagram 就是一个垂直分片的现实世界案例。当热门账号发布新图片时,点赞数会快速增长,从而导致性能问题。解决这个问题的方法之一是将点赞数从图片元数据中分离出来。

当您注意到许多查询一次仅请求几列时,这是一个很好的信号,表明您应该垂直分区表。

逻辑分片 vs 物理分片

了解数据库分片时另一个令人困惑的方面是逻辑分片与物理分片这两个术语。

逻辑分片是数据块,例如,按用户姓名的首字母 AZ 进行分块。

然后,这些逻辑分片分布在物理分片上,物理分片是在 PostgreSQL、MongoDB 或 MySQL 等服务器上运行的实际数据库节点实例。

每个逻辑分片可以有多个副本分布在多个物理实例上。这样做是为了提高可靠性。即使一台包含我们所需数据的服务器发生故障,我们的应用程序仍然可以从另一台物理分片/数据库服务器检索副本。

数据库分片的常见原因以及数据库速度慢的原因

在本节中,我将探讨导致数据库速度变慢的具体原因。原因不止一个,根据应用程序的类型,数据库可能会因为各种原因(例如 CPU、RAM 或存储限制)而遇到问题。

替代文本

硬盘限制

这可能是数据库需要分片的最容易理解的原因。在这种情况下,数据量太大,单个硬盘装不下。

即使应用程序每天只收到几个请求,你仍然需要对数据库进行分片,以确保所有数据可用。垂直扩展,也就是增加硬盘容量,只能暂时奏效,到一定程度,使用更多配备商用硬盘的机器会更经济高效。

高 CPU 利用率

如果有大量用户同时查询数据库,则 CPU 可能会成为导致数据库速度变慢的瓶颈。

在最糟糕的情况下,用户请求会开始超时,因为请求在 CPU 尝试处理时被卡在等待状态。如果你见过某个网站因为突然从 Hacker News 或 Reddit 等网站获得大量流量而瘫痪,这很可能就是原因。

在这种情况下,分片会将负载分散到多个服务器上,以便每个服务器可以处理一部分请求。

高内存利用率

从内存中获取数据比从磁盘/硬盘中查找数据要快得多。几乎所有数据库都会自动缓存最常用的数据。当数据库没有足够的内存来快速提供这些数据时,问题就开始出现了。数据库会回退到从磁盘检索数据,而这非常缓慢。

在高流量情况下,服务器将无法跟上,就像 CPU 使用率高一样,会导致用户请求超时。分片技术以类似的方式解决了这个问题:更多机器各自存储一部分数据,意味着有更多内存可用来高效地提供数据。

网络带宽

数据通过光纤电缆传输,光纤电缆的容量是固定的。如果来回发送的数据量超过该容量,请求就会开始失败。

想象一下,网络带宽就像一桶水,如果倒入的水超过了它的承载能力,它就会溢出。对于你的应用程序来说,所有溢出都会导致请求失败。

在对数据库进行分片之前可以尝试的替代方案

有许多可用于扩展数据库的选项,在尝试对数据库进行分片之前,您应该尝试使用其中的许多选项。

数据库索引

优化数据库性能的一个简单方法是根据列对表进行索引。这使得数据库能够查找查询行,而无需对表中的每一行进行全面扫描。

缓存

缓存是指将数据存储在内存中,以便更快、更高效地提供服务。正如您上面所读到的,您的数据库已经内置了一些缓存功能。为了进一步提升性能并帮助减轻数据库的流量负担,大多数应用程序都使用类似 Redis 之类的工具来构建另一个专用的缓存层。

这些专用服务器仅用于缓存,位于数据库前端。它们存储最常访问的数据,并在可能的情况下处理响应。如果它们没有存储请求的数据,则请求将被转发到数据库。

缓存图

在许多 Web 应用中,读取操作远多于写入操作。例如,Twitter 的一条推文可能被读取数百万次,而这条推文只被写入数据库一次。缓存非常适合这类读取密集型应用,因为更新频率较低。

只读副本

只读副本是数据库的克隆,配置为仅接收来自用户的读取请求。这使得它们比分片更容易实现。所有更新和写入都指向单个服务器,并且这些更改最终也会发送到所有只读副本。

只读副本

使用只读副本的一个问题是数据过时。试想一下,如果用户请求的内容已在主数据库中更新,但该更改尚未到达只读副本,会发生什么?他们会收到旧版本的数据。对于某些应用程序来说,这可能无关紧要,但对于其他应用程序来说,可能会造成严重问题。

垂直扩展

最简单的解决方案是,它不需要对数据库或应用程序进行任何更改,只需尽可能长时间地迁移到更大的服务器即可。但是,如果您的应用程序流量会长期增长,那么这基本上只是在拖延问题。

垂直扩展

结论

希望这篇文章能帮助你理解数据库分片和扩展。这是一个复杂的主题,需要花些时间才能理清头绪,所以即使你现在还头晕目眩,也不用担心。

如果您发现任何令人困惑的事情,请在下面的评论中告诉我,以便我可以更新帖子并澄清问题!

替代文本

文章来源:https://dev.to/renaissanceengineer/database-sharding-explained-2021-database-scaling-tutorial-5cej
PREV
负载均衡器教程 2020 - 系统设计基础
NEXT
适用于您下一个项目的 7 个独特 API