全面了解MongoDB分片指南

全面了解MongoDB分片指南

在当今数据驱动的世界中,数据量和数据复杂性以前所未有的速度持续增长,因此对稳健、可扩展的数据库解决方案的需求变得至关重要。据估计,到 2025 年将产生 180 ZB 的数据。这些数字都是不容忽视的。

随着数据和用户需求的激增,依赖单一数据库位置已变得不切实际。这会降低系统速度,让开发人员不堪重负。您可以采用各种解决方案来优化您的数据库,例如数据库分片

在本综合指南中,我们将深入探讨 MongoDB 分片,揭开其优点、组件、最佳实践、常见错误以及如何开始使用的神秘面纱。

什么是数据库分片?

数据库分片是一种数据库管理技术,它将不断增长的数据库横向分割成更小、更易于管理的单元(称为分片)。

随着数据库的扩展,将其划分为多个较小的部分并将每个部分分别存储在不同的机器上就变得非常实用。这些较小的部分或分片是整个数据库的独立子集。这种划分和分发数据的过程就是数据库分片的过程。

数据库分片插画

数据库分片插画 (图片来源: LinkedIn)

在实施分片数据库时,主要有两种方法:开发定制分片解决方案或付费购买现有解决方案。这就提出了一个问题:是开发分片解决方案更合适,还是付费更合适。

构建与购买分片解决方案备忘录图片

构建与购买分片解决方案备忘录图片 (图片来源: LinkedIn)

要做出这一选择,您需要考虑第三方集成的成本,同时牢记以下因素:

  • 开发人员的技能和可学习性:与产品相关的学习曲线及其与开发人员技能的匹配程度。
  • 系统提供的数据模型和应用程序接口:每个数据系统都有自己的数据表示方式。将应用程序与产品集成的便利性和易用性是一个关键的考虑因素。
  • 客户支持和在线文档:如果在集成过程中遇到困难或需要帮助,客户支持的质量和可用性以及全面的在线文档就变得至关重要。
  • 云部署的可用性:随着越来越多的公司向云过渡,确定第三方产品是否可以在云环境中部署非常重要。

基于这些因素,您现在可以决定是构建一个分片解决方案,还是花钱购买一个能为您完成繁重工作的解决方案。

目前,市场上大多数数据库都支持数据库分片。例如,MariaDB 等关系型数据库和 MongoDB 等 NoSQL 数据库

什么是 MongoDB 中的分片?

使用 NoSQL 数据库的主要目的是为了满足查询和存储大量数据的计算和存储需求。

一般来说,MongoDB 数据库包含大量的集合。每个集合都由各种文档组成,其中包含键值对形式的数据。您可以使用MongoDB分片将这个大集合拆分成多个较小的集合。这样,MongoDB 在执行查询时就不会对服务器造成太大压力。

例如,西班牙电信科技公司(Telefónica Tech)管理着全球3000多万台物联网设备。为了跟上不断增长的设备使用率,他们需要一个能够弹性扩展和管理快速增长的数据环境的平台。MongoDB的分片技术是他们的正确选择,因为它最符合他们的成本和容量需求。

利用MongoDB分片技术,Telefónica Tech每秒可运行超过115,000次查询。这相当于每秒插入30,000次数据库,延迟不到一毫秒!

MongoDB 分片的优势

以下是 MongoDB 分片为大规模数据带来的一些好处:

存储容量

我们已经看到,分片将数据分散到群集分片中。这种分布方式可让每个分片包含整个集群数据的一个片段。当数据集增大时,额外的分片将增加群集的存储容量。

读/写

MongoDB 将读写工作负载分配给分片集群中的分片,允许每个分片处理集群操作的子集。通过添加更多的分片,这两种工作负载都可以在集群中横向扩展。

高可用性

将分片和配置服务器部署为副本集可提高可用性。现在,即使一个或多个分片副本集完全不可用,分片集群也能执行部分读写。

停机保护

如果一台机器因意外停机而瘫痪,许多用户都会受到影响。在未分片的系统中,由于整个数据库都会宕机,因此影响是巨大的。通过 MongoDB 分片,可以控制不良用户体验/影响的爆炸半径。

地理分布和性能

复制的分片可以放置在不同的区域。这意味着可以为客户提供低延迟的数据访问,即把消费者请求重定向到离他们更近的分片。根据区域的数据管理策略,可以将特定分片配置到特定区域。

MongoDB 分片集群的组件

在解释了 MongoDB 分片集群的概念后,让我们深入了解一下组成这种集群的各个组件。

  1. 分片
  2. 配置服务器
  3. 查询路由器

1. 分片

每个分片都有一个分片数据子集。从 MongoDB 3.6 开始,碎片必须作为副本集部署,以提供高可用性和冗余。

分片集群中的每个数据库都有一个主分片,用于保存该数据库的所有未分片集合。主分区与副本集中的主分区无关。

要更改数据库的主分区,可以使用 movePrimary 命令。主分区迁移过程可能需要很长时间才能完成。

在此期间,您不应尝试访问与数据库相关的集合,直到迁移过程完成。根据迁移的数据量,该过程可能会影响整个群集的运行。

您可以使用 mongosh 中的 sh.status() 方法查看群集概览。该方法将返回数据库的主分块以及分块间的分块分布。

2. 配置服务器

将分片集群的配置服务器部署为副本集,可以提高整个配置服务器的一致性。这是因为 MongoDB 可以利用标准副本集读写协议来读写配置数据。

要将配置服务器作为副本集部署,必须运行 WiredTiger 存储引擎。WiredTiger 在写操作中使用文档级并发控制。因此,多个客户端可以同时修改一个集合中的不同文档。

配置服务器将分片集群的元数据存储在配置数据库中。要访问配置数据库,可以在 mongo shell 中使用以下命令:

use config

这里有几个限制需要注意:

  • 用于配置服务器的副本集配置应该没有仲裁者。仲裁者参与主服务器的选举,但它没有数据集副本,不能成为主服务器。
  • 该副本集不能有任何延迟成员。延迟成员拥有副本集的数据集副本。但延迟成员的数据集包含数据集的早期或延迟状态。
  • 您需要为配置服务器建立索引。简单地说,任何成员都不应将 members[n].buildIndexes 设置为 false

如果配置服务器副本集失去了主成员且无法选出一个,群集的元数据就会变成只读。你仍然可以读写分片,但在副本集选出主成员之前,不会发生分块或迁移。

3. 查询路由器

MongoDB mongos 实例可以充当查询路由器,让客户端应用程序和分片集群轻松连接。

从 MongoDB 4.4 开始,mongos 可以支持对冲读取,以减少延迟。有了对冲读取功能,mongos 实例会为每个被查询的分片向两个副本集成员分派读取操作。然后,它会从每个分区的第一个响应者那里返回结果。

以下是这三个组件在分片集群中的交互方式:

分片集群组件的交互

分片集群组件的交互(图片来源:MongoDB Sharding

mongos 实例将通过以下方式把查询导向一个群集:

  1. 检查需要接收查询的分片列表。
  2. 在所有目标分片上建立游标。

然后,mongos 会合并来自每个目标碎片的数据,并返回结果文档。有些查询修改器(如排序)会在 mongos 提取结果前在每个分区上执行。

在某些情况下,如果分片键或分片键前缀是查询的一部分,mongos 会执行预先计划好的操作,将查询指向群集中的分片子类。

对于生产集群,要确保数据冗余,系统高度可用。您可以选择以下配置进行生产分片群集部署:

  • 将每个分片部署为 3 个成员的副本集
  • 将配置服务器部署为 3 个成员副本集
  • 部署一个或多个 mongos 路由器

对于非生产群集,可使用以下组件部署分片群集:

  • 单个碎片副本集
  • 一个副本集配置服务器
  • 一个 mongos 实例

MongoDB 如何进行分片?

既然我们已经讨论了分片集群的不同组成部分,那么现在就该深入探讨其流程了。

要将数据分割到多个服务器上,需要使用 mongos。当你连接向 MongoDB 发送查询时,mongos 会查找并找到数据所在的位置。然后,它会从正确的服务器获取数据,如果数据被分割在多个服务器上,它还会将所有数据合并在一起。

由于这一切都将在后台完成,因此你无需在应用程序端做任何事情。MongoDB 会像普通查询连接一样运行。你的客户端将连接到 mongos,配置服务器将处理其余事宜。

如何逐步设置 MongoDB 分片?

设置 MongoDB 分片是一个涉及多个步骤的过程,以确保数据库集群的稳定和高效。下面是如何设置 MongoDB 分片的详细分步说明。

在开始之前,需要注意的是,要在 MongoDB 中设置分片,至少需要三台服务器:一台用于配置服务器,一台用于 mongos 实例,一台或多台用于分片。

  1. 从配置服务器创建目录
  2. 在配置模式下启动 MongoDB
  3. 启动 Mongos 实例
  4. 连接到 Mongos 实例
  5. 为集群添加服务器
  6. 启用数据库分片

1. 从配置服务器创建目录

首先,我们要为配置服务器数据创建一个目录。在第一台服务器上运行以下命令即可完成:

 mkdir /data/configdb

2. 在配置模式下启动 MongoDB

接下来,我们将使用以下命令在第一台服务器上以配置模式启动 MongoDB:

mongod --configsvr --dbpath /data/configdb --port 27019

这将在  port 27019 启动配置服务器,并将数据存储在 /data/configdb 目录中。请注意,我们使用 --configsvr 标志表示该服务器将用作配置服务器。

3. 启动 Mongos 实例

下一步是启动 mongos 实例。这个过程会根据分片密钥将查询路由到正确的分片。要启动 mongos 实例,请使用以下命令:

mongos --configdb :27019

替换为运行配置服务器的机器的 IP 地址或主机名。

4. 连接到 Mongos 实例

一旦运行了 mongos 实例,我们就可以使用 MongoDB shell 与之连接。运行以下命令即可实现:

mongo --host  --port 27017

在该命令中,应替换为运行 mongos 实例的服务器的主机名或 IP 地址。这将打开 MongoDB shell,允许我们与 mongos 实例交互并向集群添加服务器。

替换为运行 mongos 实例的机器的 IP 地址或主机名。

5. 为集群添加服务器

现在我们已连接到 mongos 实例,可以通过运行以下命令将服务器添加到群集中:

sh.addShard(":27017")

在该命令中,应替换为运行分片的服务器的主机名或 IP 地址。该命令将把分块添加到群集,并使其可供使用。

对要添加到群集中的每个分块重复此步骤。

6. 启用数据库分片

最后,我们将运行以下命令为数据库启用分片:

sh.enableSharding("")

在该命令中,应替换为要分片的数据库名称。这将启用指定数据库的分片功能,允许你将其数据分布到多个分片上。

就是这样!按照这些步骤,你现在应该已经拥有了一个功能齐全的 MongoDB 分片集群,可以横向扩展并处理高流量负载。

MongoDB 分片最佳实践

虽然我们已经建立了分片集群,但定期监控和维护集群对确保最佳性能至关重要。MongoDB 分片的一些最佳实践包括

  1. 确定正确的分片密钥
  2. 规划数据增长
  3. 为分片使用专用硬件
  4. 为碎片服务器使用复制集
  5. 监控分片性能
  6. 制定灾难恢复计划
  7. 适当时使用基于哈希值的分片

1. 确定正确的分片密钥

分片键是 MongoDB 分片中的一个关键因素,它决定了数据在分片间的分布方式。选择一个能在分片间均匀分布数据并支持最常见查询的分片键非常重要。应避免选择会导致热点或数据分布不均的分片键,因为这会导致性能问题。

要选择正确的分区密钥,你应该分析你的数据和你要执行的查询类型,然后选择一个满足这些要求的密钥。

2. 规划数据增长

在建立分片集群时,要为未来的增长做好规划,首先要有足够的分片来处理当前的工作负载,然后再根据需要添加更多分片。确保你的硬件和网络基础设施能够支持分片的数量和你未来预期的数据量。

3. 为分片使用专用硬件

为每个分片使用专用硬件,以获得最佳性能和可靠性。每个分片都应拥有自己的服务器或虚拟机,以便不受任何干扰地利用所有资源。

使用共享硬件会导致资源争用和性能下降,影响整个系统的可靠性。

4. 为碎片服务器使用复制集

为分片服务器使用副本集可为 MongoDB 分片集群提供高可用性和容错性。每个副本集应该有三个或更多成员,每个成员应该驻留在单独的物理机上。这种设置可确保分片集群在单个服务器或副本集成员发生故障时仍能正常运行。

5. 监控分片性能

监控分片的性能对于在问题变成大问题之前发现问题至关重要。你应该监控每个分片服务器的 CPU、内存、磁盘 I/O 和网络 I/O,以确保分片能够处理工作负载。

你可以使用 MongoDB 的内置监控工具(如 mongostatmongotop)或第三方监控工具(如 Datadog、Dynatrace 和 Zabbix)来跟踪分片性能。

6. 制定灾难恢复计划

制定灾难恢复计划对于维护 MongoDB 分片集群的可靠性至关重要。您应该制定灾难恢复计划,其中包括定期备份、测试备份以确保其有效性,以及在发生故障时恢复备份的计划。

7. 适当时使用基于哈希值的分片

当应用程序发出基于范围的查询时,范围分片是有益的,因为操作可以限制在较少的分片上,主要是单个分片。要实现这一点,你需要了解你的数据和查询模式。

散列分片可确保读写的均匀分布。不过,它不能提供高效的基于范围的操作。

分片处理 MongoDB 数据库时应避免哪些常见错误?

MongoDB 分片是一种强大的技术,可以帮助你横向扩展数据库并将数据分布到多个服务器上。不过,在对 MongoDB 数据库进行分片时,应避免几个常见错误。下面是一些最常见的错误以及如何避免它们。

  1. 选择错误的分片密钥
  2. 尝试更改分片密钥的值
  3. 未能监控群集
  4. 添加新分片等待时间过长(过载)
  5. 配置服务器不足
  6. 未能备份和还原数据
  7. 无法测试分片群集

1. 选择错误的分片密钥

在对 MongoDB 数据库进行分片时,最关键的决定之一就是选择分片密钥。分片键决定了数据在分片间的分布方式,选择错误的键会导致数据分布不均、热点和性能低下。

一个常见的错误是,在使用基于范围的分片而不是散列分片时,选择的分片键值只在新文档出现时才会增加。例如,时间戳(自然)或任何以时间为最重要组成部分的东西,如 ObjectID(前四个字节是时间戳)。

如果你选择了分片键,所有的插入都将进入范围最大的分块。即使不断添加新分块,最大写入容量也不会增加。

如果你打算扩大写入容量,可以尝试使用基于哈希值的分块密钥,这样既能使用相同的字段,又能提供良好的写入可扩展性。

2. 尝试更改分片密钥的值

对于现有文档来说,分片密钥是不可变的,这意味着你不能更改密钥。你可以在分片前进行某些更新,但不能在分片后进行。尝试修改现有文档的分片键时,会出现以下错误:

cannot modify shard key's value fieldid for collection: collectionname

您可以删除并重新插入文件来修改分块密钥,而不是尝试修改它。

3. 未能监控群集

分片会给数据库环境带来额外的复杂性,因此必须密切监控群集。不监控群集可能会导致性能问题、数据丢失和其他问题。

为避免这种错误,应设置监控工具来跟踪 CPU 使用率、内存使用率、磁盘空间和网络流量等关键指标。当超过某些阈值时,还应设置警报。

4. 添加新分区等待时间过长(超载)

在对 MongoDB 数据库进行分片时,需要避免的一个常见错误是等待添加新分片的时间过长。当一个分片的数据或查询量过大时,就会导致性能问题,拖慢整个集群的运行速度。

假设你有一个由 2 个分块组成的假想集群,其中有 20000 个块(5000 个块被视为 “活动 “块),我们需要添加第 3 个分块。第 3 个分块最终将存储三分之一的活动块(以及总块数)。

我们面临的挑战是,何时分块不再增加开销,而是成为资产。我们需要计算将活动块迁移到新分块时系统会产生的负载,以及与整个系统收益相比,什么时候可以忽略不计。

在大多数情况下,我们可以比较容易地想象到,在一组超负荷的分块上,这组迁移需要花费更长的时间,而我们新添加的分块则需要花费更长的时间才能跨过阈值,成为净收益。因此,最好在必要之前主动增加容量。

可能的缓解策略包括定期监控群集,并在流量较低时主动添加新分区,以减少对资源的竞争。建议手动平衡目标 “热门 “分块(访问量高于其他分块),以便更快地将活动转移到新分块。

5. 配置服务器不足

如果配置服务器供应不足,就会导致性能问题和不稳定性。配置不足可能是由于 CPU、内存或存储等资源分配不足造成的。

这可能导致查询性能缓慢、超时甚至崩溃。为避免这种情况,为配置服务器分配足够的资源至关重要,尤其是在较大的群集中。定期监控配置服务器的资源使用情况有助于发现资源分配不足的问题。

防止这种情况的另一种方法是为配置服务器使用专用硬件,而不是与其他群集组件共享资源。这有助于确保配置服务器有足够的资源来处理其工作负载。

6. 未能备份和恢复数据

备份对于确保数据不会在故障中丢失至关重要。数据丢失的原因多种多样,包括硬件故障、人为错误和恶意攻击。

不备份和恢复数据会导致数据丢失和停机。为避免这一错误,您应制定备份和还原策略,包括定期备份、测试备份以及将数据还原到测试环境。

7. 未测试分片群集

在将分片集群部署到生产环境之前,必须对其进行全面测试,以确保其能够处理预期的负载和查询。不测试分片群集可能会导致性能低下和崩溃。

MongoDB 分片与集群索引:哪个对大型数据集更有效?

MongoDB 分片和聚类索引都是处理大型数据集的有效策略。但它们的目的不同。选择正确的方法取决于应用程序的具体要求。

分片是一种水平扩展技术,可将数据分布到多个节点上,是处理具有高写入率的大型数据集的有效解决方案。它对应用是透明的,允许应用与 MongoDB 进行交互,就像与单个服务器交互一样。

另一方面,聚类索引允许 MongoDB 在查询匹配到索引字段时更高效地定位数据,从而提高了从大型数据集中检索数据的查询性能。那么,哪种方法对大型数据集更有效呢?答案取决于具体的使用案例和工作负载要求。

如果应用程序需要较高的写入和查询吞吐量,并且需要横向扩展,那么 MongoDB 分片可能是更好的选择。不过,如果应用程序的工作负载是读取型的,并且需要按特定顺序组织频繁查询的数据,那么聚类索引可能会更有效。

分片和聚类索引都是在 MongoDB 中管理大型数据集的强大工具。关键是要仔细评估您的应用需求和工作负载特征,以确定适合您的特定用例的最佳方法。

小结

分片集群是一种功能强大的架构,可以处理大量数据并进行横向扩展,以满足不断增长的应用需求。集群由分片、配置服务器、mongos 进程和客户端应用程序组成,数据根据精心选择的分片密钥进行分区,以确保高效分发和查询。

利用分片的强大功能,应用程序可以实现高可用性,提高性能,并有效利用硬件资源。选择正确的分片密钥对数据的均匀分布至关重要。

您对 MongoDB 和数据库分片实践有什么看法?您觉得我们应该介绍分片的哪些方面吗?请在评论中告诉我们!

评论留言