了解数据库分片

近年来,分片数据库一直受到很多关注,但是许多人并没有清楚地了解它们是什么或者对数据库进行分片可能有意义的情况。这篇概念性文章讨论了分片是什么,它的一些主要优点和缺点,以及一些常见的分片方法。

介绍

任何看到显着增长的应用程序或网站最终都需要扩展以适应流量的增加。 对于数据驱动的应用程序和网站,以确保数据安全性和完整性的方式进行扩展至关重要。 可能很难预测网站或应用程序的流行程度或维持流行程度的时间长短,这就是为什么有些组织选择允许它们动态扩展数据库的数据库体系结构的原因。

在这篇概念性文章中,我们将讨论一种这样的数据库架构:分片数据库 近年来,Sharding一直受到很多关注,但许多人并没有清楚地了解它是什么,或者对数据库进行分片可能有意义的场景。 我们将讨论分片是什么,它的一些主要优点和缺点,以及一些常见的分片方法。

什么是Sharding?

Sharding是一种与水平分区相关的数据库体系结构模式 - 将一个表的行分成多个不同的表(称为分区 )的做法。 每个分区都具有相同的模式和列,但也有完全不同的行。 同样,每个数据中保存的数据都是唯一的,并且与其他分区中保存的数据无关。

考虑水平分区与垂直分区的关系,可能会有所帮助。 在垂直分区表中,整个列被分离出来并放入新的不同表中。 保持在一个垂直分区内的数据独立于所有其他分区中的数据,并且每个数据都包含不同的行和列。 下图说明了如何在水平和垂直方向上对表进行分区:

显示水平和垂直分区的示例表

分片涉及将一个数据分成两个或多个较小的块,称为逻辑分片 然后,逻辑分片分布在单独的数据库节点上,称为物理分片 ,可以容纳多个逻辑分片。 尽管如此,所有分片中保存的数据共同代表整个逻辑数据集。

数据库分片举例说明了无共享架构 这意味着分片是自治的; 它们不共享任何相同的数据或计算资源。 但是,在某些情况下,将某些表复制到每个分片中作为参考表可能是有意义的。 例如,假设某个应用程序的数据库依赖于重量测量的固定转换率。 通过将包含必要转换率数据的表复制到每个分片中,有助于确保查询所需的所有数据都保存在每个分片中。

通常,在应用程序级别实现分片,这意味着应用程序包含定义传输读取和写入的分片的代码。 但是,某些数据库管理系统内置了分片功能,允许您直接在数据库级别实现分片。

鉴于分片的这种一般概述,让我们回顾一下与此数据库体系结构相关的一些正面和负面的内容。

分片的好处

分片数据库的主要吸引力在于它可以帮助促进水平缩放 ,也称为缩小 水平扩展是向现有添加更多计算机的做法,以便分散负载并允许更多流量和更快的处理。 这通常与垂直缩放形成对比,也称为向上扩展 ,这涉及升级现有服务器的硬件,通常是添加更多RAM或CPU。

让关系数据库在单个机器上运行并通过升级其计算资源根据需要进行扩展是相对简单的。 但最终,任何非分布式数据库在存储和计算能力方面都会受到限制,因此可以自由地水平扩展,使您的设置更加灵活。

某些人可能选择分片数据库体系结构的另一个原因是加快查询响应时间。 当您对尚未分片的数据库提交查询时,可能必须先搜索您查询的表中的每一行,然后才能找到您要查找的结果集。 对于具有大型单片数据库的应用程序,查询可能变得极其缓慢。 但是,通过将一个表分成多个,查询必须遍历更少的行,并且返回结果集的速度要快得多。

通过减少中断的影响,分片还可以帮助使应用程序更可靠。 如果您的应用程序或网站依赖于未加密的数据库,则中断可能会导致整个应用程序不可用。 但是,对于分片数据库,中断可能只会影响单个分片。 即使这可能使某些用户无法使用某些应用程序或网站部分,但整体影响仍会低于整个数据库崩溃的影响。

分片的缺点

虽然对数据库进行分片可以使扩展更容易并提高性能,但它也可能会带来某些限制。 在这里,我们将讨论其中的一些以及为什么它们可能是完全避免分片的原因。

人们遇到分片的第一个困难是正确实现分片数据库体系结构的复杂性。 如果操作不正确,则分片过程可能会导致数据丢失或表损坏。 即使正确完成,分片也可能对您团队的工作流程产生重大影响。 用户必须跨多个分片位置管理数据,而不是从单个入口点访问和管理一个数据,这可能会对某些团队造成破坏。

用户在对数据库进行分片后有时会遇到的一个问题是分片最终会变得不平衡。 举例来说,假设您有一个带有两个单独分片的数据库,一个用于姓氏以字母A到M开头的客户,另一个用于名称以字母N到Z开头的客户。但是,您的应用程序服务量过大姓氏以字母G开头的人。因此,AM分片逐渐累积的数据多于新西兰分片,导致应用程序减慢并停止用户的大部分。 AM分片已成为所谓的数据库热点 在这种情况下,通过减速和崩溃来消除分片数据库的任何好处。 数据库可能需要修复和重新分片才能实现更均匀的数据分发。

另一个主要缺点是,一旦对数据库进行了分片,将其返回到其未加密的体系结构可能非常困难。 在分片之前对数据库进行的任何备份都不包括自分区以来写入的数据。 因此,重建原始的非分支架构需要将新的分区数据与旧备份合并,或者将分区的DB转换回单个DB,这两者都是昂贵且耗时的努力。

要考虑的最后一个缺点是每个数据库引擎本身都不支持分片。 例如,PostgreSQL不包括自动分片作为功能,尽管可以手动分片PostgreSQL数据库。 有许多Postgres分支包括自动分片,但这些分支通常落后于最新的PostgreSQL版本,缺乏某些其他功能。 一些专门的数据库技术 - 如MySQL Cluster或某些数据库即服务产品(如MongoDB Atlas)确实包含自动分片功能,但这些数据库管理系统的vanilla版本却没有。 因此,分片通常需要“自己动手”的方法。 这意味着通常很难找到用于分片的文档或用于解决问题的提示。

当然,这些只是在分片之前要考虑的一些一般性问题。 根据其用例,对数据库进行分片可能存在许多潜在的缺点。

现在我们已经介绍了一些分片的缺点和好处,我们将讨论一些分片数据库的不同架构。

分片架构

一旦你决定对你的数据库进行分片,你需要弄清楚的是你将如何去做。 在运行查询或将传入数据分发到分片表或数据库时,它必须转到正确的分片。 否则,它可能导致数据丢失或查询速度缓慢。 在本节中,我们将介绍一些常见的分片架构,每个架构使用稍微不同的过程来跨分片分发数据。

基于密钥的分片

基于密钥的分片 (也称为基于散列的分片 )涉及使用从新写入的数据中获取的值 - 例如客户的ID号,客户端应用程序的IP地址,邮政编码等 - 并将其插入哈希函数以确定哪个分片数据应该去。 哈希函数是将一段数据(例如,客户电子邮件)作为输入并输出离散值(称为哈希值)的函数 在分片的情况下,散列值是一个分片ID,用于确定传入数据将存储在哪个分片上。 总而言之,这个过程看起来像这样:

基于密钥的分片示例图

为了确保条目以正确的方式放置在正确的分片中,输入散列函数的值应该都来自同一列。 此列称为分片 简单来说,分片键与主键类似,因为它们都是用于为各行建立唯一标识符的列。 一般来说,分片键应该是静态的,这意味着它不应包含可能随时间变化的值。 否则,它会增加更新操作的工作量,并可能降低性能。

虽然基于密钥的分片是一种相当常见的分片架构,但在尝试动态添加或删除数据库中的其他服务器时,它会使事情变得棘手。 在添加服务器时,每个服务器都需要一个相应的哈希值,并且许多现有条目(如果不是全部)都需要重新映射到新的正确哈希值,然后迁移到相应的服务器。 当您开始重新平衡数据时,新旧散列函数都不会有效。 因此,您的服务器将无法在迁移期间写入任何新数据,您的应用程序可能会停机。

该策略的主要吸引力在于它可以用于均匀分布数据以防止热点。 此外,由于它以算法方式分配数据,因此无需维护所有数据所在位置的映射,这是其他策略(如范围或基于目录的分片)所必需的。

基于范围的分片

基于范围的分片涉及基于给定值的范围分片数据。 为了说明,假设您有一个数据库,用于存储零售商目录中所有产品的信息。 您可以创建一些不同的分片,并根据每个产品的价格范围分配每个产品的信息,如下所示:

基于范围的分片示例图

基于范围的分片的主要好处是它实现起来相对简单。 每个分片都包含一组不同的数据,但它们都具有相同的模式,以及原始数据库。 应用程序代码只读取数据所属的范围并将其写入相应的分片。

另一方面,基于范围的分片不保护数据不均匀分布,导致上述数据库热点。 查看示例图,即使每个分片拥有相同数量的数据,特定产品的可能性也会高于其他产品。 反过来,它们各自的分片将接收不成比例的读数。

基于目录的分片

要实现基于目录的分片 ,必须创建并维护一个查找表 ,该查找表使用分片键来跟踪哪个分片包含哪些数据。 简而言之,查找表是一个表,其中包含有关可以找到特定数据的静态信息集。 下图显示了基于目录的分片的简单示例:

基于目录的分片示例图

此处, Delivery Zone列定义为分片键。 来自分片键的数据被写入查找表以及应该写入每个相应行的任何分片。 这与基于范围的分片类似,但不是确定分片键的数据落入哪个范围,而是将每个键绑定到其自己的特定分片。 在分片键具有低基数并且分片存储一系列键没有意义的情况下,基于目录的分片是基于范围的分片的理想选择。 请注意,它也不同于基于密钥的分片,因为它不通过散列函数处理分片键; 它只是根据查找表检查密钥,以查看数据需要写入的位置。

基于目录的分片的主要吸引力在于其灵活性。 基于范围的分片架构限制您指定值的范围,而基于密钥的分片限制您使用固定的散列函数,如前所述,稍后可能非常难以更改。 另一方面,基于目录的分片允许您使用您想要将数据条目分配给分片的任何系统或算法,并且使用此方法动态添加分片相对容易。

虽然基于目录的分片是这里讨论的最灵活的分片方法,但是在每次查询或写入之前连接到查找表的需要会对应用程序的性能产生不利影响。 此外,查找表可能成为单点故障:如果它被损坏或以其他方式失败,它可能会影响一个人编写新数据或访问其现有数据的能力。

我应该碎片吗?

是否应该实现分片数据库架构几乎总是一个争论的问题。 有些人认为分片是达到一定规模的数据库的必然结果,而其他人则认为这是一个令人头疼的问题,除非绝对必要,否则应该避免,因为分片增加了操作的复杂性。

由于这种增加的复杂性,通常仅在处理非常大量的数据时才执行分片。 以下是一些常见方案,其中对数据库进行分片可能是有益的:

  • 应用程序数据量增长到超过单个数据库节点的存储容量。
  • 对数据库的写入或读取量超过单个节点或其读取副本可以处理的量,从而导致响应时间减慢或超时。
  • 应用程序所需的网络带宽超过单个数据库节点和任何只读副本可用的带宽,从而导致响应时间减慢或超时。

在分片之前,您应该用尽所有其他选项来优化数据库。 您可能需要考虑的一些优化包括:

  • 设置远程数据库 如果您正在使用其所有组件都驻留在同一服务器上的单一应用程序,则可以通过将其移动到自己的计算机来提高数据库的性能。 由于数据库的表保持不变,因此这不会增加分片的复杂性。 但是,它仍允许您将数据库与其他基础结构进行垂直扩展。
  • 实现缓存 如果您的应用程序的读取性能导致您遇到麻烦,那么缓存是一种可以帮助改进它的策略。 缓存涉及临时存储已在内存中请求的数据,以便您以后更快地访问它。
  • 创建一个或多个只读副本 另一种有助于提高读取性能的策略,包括将数据从一个数据库服务器( 主服务器 )复制到一个或多个辅助服务器 在此之后,每个新写入在复制到辅助节点之前都会转到主节点,而只能对辅助服务器进行读取。 像这样分发读写可以防止任何一台机器承担过多的负载,从而有助于防止速度下降和崩溃。 请注意,创建只读副本涉及更多的计算资源,因此需要花费更多的钱,这可能是一些人的重要约束。
  • 升级到更大的服务器 在大多数情况下,将一个人的数据库服务器扩展到具有更多资源的计算机比分片需要更少的工作量。 与创建只读副本一样,具有更多资源的升级服务器可能会花费更多的钱。 因此,如果它真的最终成为您的最佳选择,您应该只进行调整大小。

请记住,如果您的应用程序或网站超过某一点,那么这些策略都不足以提高自己的性能。 在这种情况下,分片可能确实是您的最佳选择。

结论

对于那些希望横向扩展数据库的人来说,分片是一个很好的解决方案。 但是,它还会增加很多复杂性,并为您的应用程序创建更多潜在的故障点。 某些人可能需要进行分片,但创建和维护分片结构所需的时间和资源可能会超过其他人的利益。

通过阅读这篇概念性文章,您应该更清楚地了解分片的优缺点。 展望未来,您可以使用此洞察力来更明智地决定分片数据库体系结构是否适合您的应用程序。


分享按钮