分片
分片是一种跨多台机器分布数据的方法。MongoDB 使用分片来支持超大数据集和高吞吐量操作的部署。
存在大型数据集或高吞吐量应用程序的数据库系统可能对单个服务器的容量构成挑战。例如,较高的查询速率可能会耗尽服务器的 CPU 容量。大于系统 RAM 的工作集大小会对磁盘驱动器的 I/O 容量造成压力。
有两种方法可解决系统增长问题:垂直扩展和水平扩展。
Vertical Scaling(垂直扩展)涉及增大单个服务器的容量,例如使用更强大的 CPU、添加更多 RAM 或增加存储空间量。可用技术所存在的限制可能会导致单个机器对给定工作负载来说不够强大。此外,基于云的提供商存在基于可用硬件配置的硬上限。因此,垂直扩展存在实际的最大值。
Horizontal Scaling(横向扩展)涉及将系统数据集和负载划分到多个服务器,以及按需增加服务器以提高容量。虽然单个机器的总体速度或容量可能不高,但每个机器均可处理总体工作负载的一部分,因此可能会比单个高速、高容量服务器提供更高的效率。扩展部署的容量只需按需添加额外的服务器,而这可能会比单个机器的高端硬件的整体成本更低。但代价在于它会增大部署的基础设施与维护的复杂性。
MongoDB 支持通过分片进行水平扩展。
您可以在用户界面中为托管在 MongoDB Atlas 中的部署进行集合分片。
分片集群
注意
下图描述了分片集群内各组件之间的交互:
MongoDB 在集合级别对数据进行分片,从而将集合数据分布到集群中的分片上。
分片键
MongoDB 使用分片键在分片之间分发集合的文档。 分片键由文档中的一个或多个字段组成。
分片集合中的文档可能缺少分片键字段。跨分片分发文档时,缺少的分片键字段将视为具有 null 值,但在路由查询时则不会。有关更多信息,请参阅缺少分片键字段。
您在对集合进行分片时会选择分片键。
文档的分片键值决定了其在各分片中的分布。您可以更新文档的分片键值,除非您的分片键字段是不可变的 _id
字段。有关详细信息,请参阅更改文档的分片键值。
分片键索引
要对已填充的集合进行分片,该集合必须具有以分片键开头的索引。对空集合进行分片时,如果该集合还没有指定分片键的适当索引,MongoDB 会创建支持索引。请参阅分片键索引。
分片键策略
分片键的选择会影响分片集群的性能、效率和可扩展性。 具有最佳硬件和基础架构的集群可能会因为选择分片键而遇到瓶颈。 分片键及其后备索引的选择也会影响集群可以使用的分片策略。
数据段
负载均衡器和均匀数据分布
分片的优点
读取/写入
MongoDB 在分片集群中的分片之间分配读写工作负载,支持每个分片处理集群操作的子集。通过添加更多的分片,读写工作负载都可以在集群中横向扩展。
对于包含分片键或复合分片键前缀的查询,mongos
可将查询定向到特定分片或一组分片。这些有针对性的操作通常比向集群中的每个分片进行广播更为有效。
存储容量:
分片将数据分布在集群中的分片上,从而允许每个分片包含整个集群数据的子集。随着数据集的增长,更多的分片会增加集群的存储容量。
高可用性
按副本集部署配置服务器和分片,可提高可用性。
即使一个或多个分片副本集变为完全不可用,分片集群仍可继续执行部分读取和写入操作。换言之,即便无法访问不可用分片上的数据,针对可用分片的读取或写入仍可成功完成。
分片前的考虑因素
需要对分片集群基础架构的需求和复杂性进行仔细规划、执行和维护。
虽然您可在后续对集合重新分片,但请务必仔细考虑分片键的选择,以免出现可扩展性与性能问题。
要了解集合分片操作的要求和限制,请参阅分片集群中的操作限制。
如果查询不含分片键或复合分片键的前缀,mongos
则会执行广播操作,从而查询分片集群中的所有分片。这些分散/聚集查询可能会长时间运行。
从 MongoDB 5.1 开始,在启动、重新启动或添加含 sh.addShard()
的分片服务器时,必须设置集群范围的写关注 (CWWC)。
如果未设置 CWWC
,并且将分片配置成默认写关注为 { w : 1 }
,将无法启动或添加分片服务器并返回错误。
请参阅默认写关注计算,详细了解如何计算默认写关注。
注意
如果您与 MongoDB 签订了有效的支持合同,请考虑联系您的客户代表,以获取分片集群规划和部署方面的帮助。
分片和非分片集合
数据库可混合使用分片和未分片集合。分片集合会进行分区并分布在集群的各个分片上。分片片集合可以位于任何分片上,但不能跨分片。
连接到分片集群
您必须连接到 mongos 路由器才能与分片集群中的任意集合进行交互。其中包括分片和非分片集合。客户端永不应连接到单个分片来执行读取或写入操作。
您可像使用 mongosh
或 MongoDB 驱动程序以连接到 mongod
一样来连接 mongos
。
注意
从MongoDB 8.0开始,您只能在分片上运行某些命令。 如果您尝试直接连接到分分片并运行不受支持的命令, MongoDB将返回错误:
"You are connecting to a sharded cluster improperly by connecting directly to a shard. Please connect to the cluster via a router (mongos)."
要直接对分片运行不支持的数据库命令,您必须连接到mongos
或具有仅维护的directShardOperations
角色。
分片策略
MongoDB 支持两种分片策略,可在多个分片集群之间分配数据。
哈希分片
哈希分片涉及计算分片键字段值的哈希值。然后,根据哈希分片键值为每个数据段分配一个范围。
提示
在使用哈希索引解析查询时,MongoDB 会自动计算哈希值。应用程序无需计算哈希值。
虽然分片键的范围可能“相近”,但它们的哈希值却不太可能位于同一数据段。基于哈希值的数据分配可促进更均匀的数据分布,尤其是在分片键单调变化的数据集中。
然而,哈希分布意味着对分片键进行基于范围的查询时,不太可能以单个分片为目标,从而导致更多的集群范围的广播操作
请参阅哈希分片以了解更多信息。
范围分片
范围分片涉及根据分片键值将数据划分为多个范围。然后,根据分片键值为每个数据段分配一个范围。
具有“相近”数值的一系列分片键更有可能位于同一个数据段上。这允许进行有针对性的操作,因为 mongos
只能将操作路由到包含所需数据的分片。
范围分片的效率取决于所选分片键。考虑不周的分片键可能会导致数据分布不均,从而抵消分片的某些好处甚或导致性能瓶颈。请参阅针对基于范围的分片的分片键选择。
有关更多信息,请参阅范围分片。
分片集群中的区域
区域可帮助改善跨多个数据中心的分片集群的数据局部性。
在分片集群中,可以根据分片键创建分片数据区域。您可以将每个区域与集群中的一个或多个分片相关联。一个分片可以与任意数量的区域关联。在均衡的集群中,MongoDB 仅将区域覆盖的数据段迁移到与该区域相关联的分片。
每个区域涵盖分片键值的一个或多个范围。某一区域所覆盖的每个范围始终包括其下边界,而不包括其上边界。
为要覆盖的区域定义范围时,必须使用分片键中包含的字段。如果使用的是复合分片键,此范围则须包含分片键的前缀。请参阅区域中的分片键以了解更多信息。
在选择分片键时,应考虑将来可能使用区域的情况。
提示
在对空的或不存在的集合进行分片之前设置区域和区域范围可更快地设置分区分片。
请参阅区域以了解更多信息。
分片中的排序规则
使用带 collation :
{ locale : "simple" }
选项的 shardCollection
命令对具有默认排序规则的集合进行分片。要成功进行分片,必须满足以下条件:
集合必须具有其前缀为分片键的索引
索引必须具有排序规则
{ locale: "simple" }
在使用排序规则创建新的集合时,请确保在对集合进行分片之前满足这些条件。
注意
对分片集合的查询会继续使用为集合配置的默认排序规则。要使用分片键索引的 simple
排序规则,请在查询的排序规则文档中指定 {locale : "simple"}
。
有关分片和排序规则的更多信息,请参阅 shardCollection
。
Change Streams
变更流可用于副本集和分片的集群。 变更流允许应用程序访问权限实时数据更改,而不会出现oplog的复杂性和风险。 应用程序可以使用变更流订阅一个或多个集合上的所有数据更改。
事务
随着分布式事务的引入,多文档事务可在分片集群上使用。
在事务进行提交前,在事务中所做的数据更改在事务外不可见。
不过,当事务写入多个分片时,并非所有外部读取操作都需等待已提交事务的结果在各个分片上可见。例如,如果事务已提交并且写入 1 在分片 A 上可见,但写入 2 在分片 B 上尚不可见,则读关注 "local"
处的外部读取可以在不看到写入 2 的情况下读取写入 1 的结果。
了解详情
《实用 MongoDB 聚合》电子书
有关分片如何与聚合配合使用的更多信息,请阅读实用 MongoDB 聚合电子书中的“分片”章节。