分片
分片是一种将数据分布到多台机器的方法。MongoDB使用分片来支持具有非常大的数据集和高吞吐量操作的部署。
具有大量数据集或高吞吐量应用的数据库系统可能会挑战单台服务器的容量。例如,高查询率可能会耗尽服务器的CPU容量。超过系统RAM的工作集大小会压力磁盘驱动器的I/O容量。
有两种方法可以解决系统增长:垂直扩展和水平扩展。
垂直扩展涉及增加单台服务器的容量,例如使用更强大的CPU、添加更多RAM或增加存储空间。可用的技术限制可能会限制单台机器对于特定工作负载的足够强大。此外,基于云的提供商基于可用的硬件配置有硬性上限。因此,垂直扩展实际上有一个上限。
水平扩展涉及将系统数据集和负载分配到多台服务器上,根据需要添加额外的服务器以增加容量。虽然单台机器的整体速度或容量可能不高,但每台机器处理整体工作负载的一部分,可能比单台高速高容量的服务器提供更好的效率。仅需要根据需要添加额外的服务器来扩展部署的容量,这可能比单台机器的高端硬件成本低。权衡是增加了部署的基础设施和维护的复杂性。
MongoDB通过分片支持水平扩展。
分片集群
注意
以下图形描述了分片集群内组件之间的交互
MongoDB 在 集合 级别分片数据,将集合数据分布在集群中的分片上。
分片键
MongoDB 使用 分片键 在分片之间分配集合的文档。分片键由文档中的一个字段或多个字段组成。
分片集合中的文档可能缺少分片键字段。在分配文档到分片时,缺少的分片键字段被视为 null 值,但在路由查询时不是。有关更多信息,请参阅 缺少分片键字段。
您在 分片集合 时选择分片键。
文档的分片键值决定了其在分片间的分布。除非您的分片键字段是不可变的_id
字段,否则您可以更新文档的分片键值。有关更多信息,请参阅更改文档的分片键值。
分片键索引
为了分片一个已填充的集合,该集合必须有一个以分片键开头的索引。当分片一个空的集合时,如果集合还没有为指定的分片键创建适当的索引,MongoDB将创建支持索引。请参阅分片键索引。
分片键策略
分片键的选择会影响分片集群的性能、效率和可扩展性。即使硬件和基础设施都非常好,选择错误的分片键也可能成为瓶颈。分片键及其支持索引的选择也可能影响集群可以使用的分片策略。
数据块
平衡器和数据均匀分布
分片的优势
读取/写入
MongoDB 将读写负载分布到分片中,允许每个分片处理集群操作的一部分。通过添加更多分片,可以在集群中水平扩展读写负载。
对于包含分片键或复合分片键前缀的查询,mongos
可以针对特定分片或一组分片进行查询。这些定向操作通常比广播到集群中的每个分片更高效。
存储容量
分片将数据分布到集群中的分片,允许每个分片包含集群数据的一部分。随着数据集的增长,添加额外的分片可以增加集群的存储容量。
高可用性
将配置服务器和分片作为副本集部署可以提供更高的可用性。
即使一个或多个分片副本集完全不可用,分片集群仍可以继续执行部分读取和写入操作。也就是说,虽然无法访问不可用的分片(s)上的数据,但针对可用分片进行的读取或写入操作仍然可以成功。
在分片之前要考虑的事项
分片集群的基础设施要求和复杂性需要仔细规划、执行和维护。
虽然您可以在以后重新分片您的集合,但仔细考虑分片键的选择以避免可扩展性和性能问题是重要的。
有关对您的集合进行分片的操作要求和限制,请参阅分片集群中的操作限制。
如果查询不包括分片键或复合分片键的前缀,mongos
将执行一个广播操作,查询分片集群中的所有分片。这些散点/收集查询可能是长时间运行的操作。
从MongoDB 5.1开始,在启动、重启或添加分片服务器时使用sh.addShard()
,必须设置全局写关注(CWWC)。
如果未设置 CWWC
且分片配置了默认写入关注度(默认写入关注度)为 { w : 1 }
,分片服务器将无法启动或添加,并返回错误。
有关默认写入关注度计算详情,请参阅 默认写入关注度计算。
注意
如果您与MongoDB有有效的支持合同,请考虑联系您的账户代表以获取关于分片集群规划和部署的协助。
分片和非分片集合
数据库可以包含分片和非分片集合的混合。分片集合是 分区 并分布到集群中的各个 分片 上。非分片集合可以位于任何分片上,但不能跨越分片。
连接到分片集群
您必须连接到 mongos 路由器才能与 分片集群 中的任何集合交互。这包括分片和未分片集合。客户端不应直接连接到单个分片以执行读写操作。
您可以使用与连接到 mongod
相同的方式连接到 mongos
,使用 mongosh
或 MongoDB 驱动程序。
注意
从 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。应用程序可以使用更改流订阅集合或集合上的所有数据更改。
交易
随着分布式事务的引入,分片集群上提供了多文档事务。
但是,直到事务提交之前,事务中对数据进行更改在事务外部是不可见的。
然而,当一个事务写入多个分片时,并非所有的外部读取操作都需要等待提交事务的结果在整个分片间可见。例如,如果一个事务提交了,在分片A上可见写入1,但在分片B上写入2尚未可见,那么在读取关注点"local"
的外部读取可以读取写入1的结果,而无需看到写入2。
了解更多
《实用的MongoDB聚合E-Book》
有关分片与聚合操作如何工作的更多信息,请阅读《Practical MongoDB Aggregations》中的分片章节。[链接](https://www.practical-mongodb-aggregations.com/guides/sharding.html) e-book。