[mongo] {第七部分} mongodb sharding
分片
分片是一种用于在多台计算机之间分配数据的方法。MongoDB使用分片来支持具有非常大的数据集和高吞吐量操作的部署。
具有大数据集或高吞吐量应用程序的数据库系统对单个服务器的具有很大挑战。例如,高查询率可能会耗尽服务器的CPU容量。大于系统RAM的工作集大小会增加磁盘驱动器的I / O容量。
解决系统增长的方法有两种:垂直扩容和水平扩展。
垂直扩容涉及增加单个服务器的容量,例如使用功能更强大的CPU,添加更多RAM或增加存储空间量。可用技术的局限性可能会限制一台计算机对于给定的工作负载而言功能不足。此外,基于云的提供程序具有基于可用硬件配置的严格上限。结果,垂直缩放有一个实际的最大值。
水平扩展涉及划分系统数据集并在多台服务器上加载,并添加其他服务器以根据需要增加容量。虽然单台计算机的整体速度或容量可能不高,但是每台计算机只能处理一部分整体工作负载,因此与单台高速大容量服务器相比,可能提供更高的效率。扩展部署的容量仅需要根据需要添加其他服务器,这可以比单台机器的高端硬件降低总体成本。折衷方案是增加基础结构和部署维护的复杂性。
MongoDB通过分片支持水平扩展。
群集分片
MongoDB群集分片由以下组件组成:
- shard:每个shard包含被分片数据的子集。每个分片都可以部署为副本集。
- mongos:mongos充当查询路由器,在客户端应用程序和分片群集之间提供接口。从MongoDB 4.4开始,mongos可以支持 hedged reads以最大程度地减少延迟。
- config服务器:配置服务器存储集群的元数据和配置设置。
下图描述了分片群集中组件的交互:
MongoDB在collection级别分片数据,从而将收集数据分布在集群中的各个分片上。
Shard
shard包含被分片的数据的一个子集分片簇。群集的分片一起保存了群集的整个数据集。
从MongoDB 3.6起,必须将分片部署为replica set,以提供冗余和高可用性。
用户,客户端或应用程序应仅直接连接到分片以执行本地管理和维护操作。
在单个分片上执行查询只会返回一部分数据。连接到mongos以执行集群级别的操作,包括读取或写入操作。
重要:MongoDB不保证任何两个连续的chunk 都驻留在单个分片上。
主分片
分片群集中的每个数据库都有一个主分片,其中包含该数据库的所有未分片集合。每个数据库都有其自己的主分片。主分片与副本集中的主分片没有任何关系。
mongos当创建新数据库时,通过在数据量最少的集群中选择分片,该选择器将选择主分片。 mongos将命令totalSize返回的字段 listDatabase用作选择条件的一部分。
要更改数据库的主分片,请使用movePrimary命令。迁移主分的过程可能需要很长时间才能完成,在迁移完成之前,无法访问有关联的集合。根据迁移的数据量,迁移可能会影响整个群集操作。在尝试更改主分片之前,请考虑对群集操作和网络负载的影响。
当您使用以前用作副本集的分片部署新的碎片群集时,所有现有数据库将继续驻留在其原始副本集上。随后创建的数据库可以驻留在集群中的任何分片上。
Shard Status
使用 sh.status() 方法来查看集群的基本信息(包括哪个shard是数据库的主shard以及跨shard的块分布)。
分片群集安全性
使用内部/成员身份验证可以加强集群内部的安全性,并防止未经授权的集群组件访问集群。您必须mongod使用适当的安全设置启动集群中的每个服务器,以强制执行内部身份验证。
分片本地用户
每个分片均支持基于角色的访问控制 (RBAC),用于限制对分片数据和操作的未授权访问。mongod 使用--auth强制RBAC的选项启动副本集中的每个副本。另外,对群集内部安全性强制执行内部/成员身份验证也可以通过RBAC进行用户访问控制。
每个分片都有其自己的分片本地用户。这些用户不能用于其他分片,也不能用于通过进行连接mongos。
Config Servers(元数据)
重要:从3.4开始,mongod 不再支持SCCC。在将分片群集升级到3.4之前,必须将配置服务器从SCCC转换为CSRS。
配置服务器存储分片群集的元数据。元数据反映分片群集中所有数据和组件的状态和组织。元数据包括每个分片上的块列表以及定义块的范围。
该mongos实例缓存此数据,并将其用于路由读取和在正确的sharad进行写入。mongos 当集群的元数据发生更改时(例如Chunk Splits或添加shard)会更新缓存。分片也可以从配置服务器读取chunk元数据。
配置服务器还存储身份验证配置信息,例如基于角色的访问控制或群集的内部身份验证设置。
MongoDB还使用配置服务器来管理分布式锁。
每个分片群集必须具有自己的配置服务器。不要将相同的配置服务器用于不同的分片群集。
警告
在配置服务器上执行的管理操作可能会对分片群集的性能和可用性产生重大影响。根据受影响的配置服务器的数量,群集可能在一段时间内处于只读或脱机状态。
副本集配置服务器
在版本3.4中更改。
从MongoDB 3.2开始,分片群集的配置服务器可以部署为副本集(CSRS),而不是三个镜像配置服务器(SCCC)。为配置服务器使用副本集可提高配置服务器之间的一致性,因为MongoDB可以利用配置文件的标准副本集读写协议。另外,将副本集用于配置服务器允许分片群集具有3个以上的配置服务器,因为副本集最多可具有50个成员。要将配置服务器部署为副本集,配置服务器必须运行WiredTiger存储引擎。
当用于配置服务器时,以下限制适用于副本集配置:
- 不允许使用仲裁者。
- 不允许使用延时节点。
- 必须建立索引(即,任何成员都不可将 buildIndexes设置设置为false)。
在配置服务器读取和写入操作
配置服务器上要有admin数据库和config数据库。
配置服务的写入
admin数据库包含与身份验证和授权有关的集合以及其他供内部使用system.*。的集合。
配置数据库包含集合(分片群集的元数据的集合)。当元数据发生更改时(例如,在块迁移或块拆分之后),MongoDB会将数据写入配置数据库。
用户应避免在正常操作或维护过程中直接写入config数据库。
当写入配置服务器,MongoDB使用一个"majority"的write concern。
从配置服务读取
MongoDB从admin数据库中读取身份验证和授权数据以及其他内部用途。
MongoDB在mongos 开始或元数据更改后(例如在块迁移之后)从config数据库读取。分片还从配置服务读取块元数据。
从副本集配置服务读取数据时,MongoDB使用"majority"的Read Concern。
配置服务器可用性
如果配置服务副本集primary不可用,将无法选举primary,则集群的元数据将变为只读。您仍然可以从分片读取和写入数据,但是在副本集可以选择主副本之前,不会发生任何块迁移或块拆分。
在分片簇,mongod和mongos实例监控分片集群中的副本集(例如shard replica sets, config server replica set)。
如果所有配置服务器都不可用,则群集可能无法运行。为了确保配置服务器保持可用和完整,配置服务器的备份至关重要。与集群中存储的数据相比,配置服务器上的数据很小,并且配置服务器的活动负载相对较低。
分片群集的元数据
配置服务器将元数据存储在配置数据库中。
重要
config在配置服务器上进行任何维护之前,请始终备份数据库。
Mongos(路由)
MongoDB 的mongos实例路由查询并将操作写入分片群集中的分片。mongos从应用程序的角度来看,它是分片群集的唯一接口。应用程序无法与shard直接连接或通信。
mongos通过缓存来自配置服务器的元数据来跟踪是哪个shard上的数据。mongos使用元数据将操作从应用程序和客户端路由到mongod实例。mongos没有持久状态,消耗的系统资源最少。
最常见的做法是在与应用服务器相同的系统上运行mongos实例,但是您可以在shard或其他专用资源上维护mongos实例。
路由和结果进程(Routing And Results Process)
mongos实例路由查询到集群:
- 确定必须接收查询的分片列表。
- 在所有目标分片上建立游标。
mongos合并来自每个target shard的数据,并返回结果的文档。在mongos检索结果之前,对每个shard执行某些查询操作,例如排序。
在版本3.6中更改:对于在多个分片上运行的聚合操作,如果这些操作不需要在数据库的主分片上运行,则这些操作可能会将结果路由回到mongos来合并结果。
在两种情况下,mongod无法进行管道操作。
第一种情况发生在拆分管道的合并部分包含必须在主分片上运行的阶段时。例如,如果$lookup要求访问与正在运行聚合的分片集合位于同一数据库中的未分片集合,则合并必须在主分片上运行。
第二种情况发生在拆分管道的合并部分包含可以将临时数据写入磁盘的stage时,例如$group,并且客户机指定了owDiskUse:true。在这种情况下,假设合并管道中没有其他阶段需要主分片,则合并将在聚合目标分片集中随机选择的分片上运行。
有关如何在分片集群查询的组件之间拆分聚合工作的更多信息,请使用解释:正确aggregation()调用的参数。返回将包括三个json对象。mergeType显示合并阶段发生的位置(“primaryShard”、“anyShard”或“mongos”)。splitPipeline显示管道中的哪些操作在单个碎片上运行。碎片显示每个碎片所做的工作。
在某些情况下,当分片键或分片键的前缀是查询的一部分时,会mongos执行 targeted operation,将查询路由到集群中的分片的子集。
mongos对不包含分片 键的查询执行广播操作( broadcast operation),将查询路由到集群中的所有分片。确实包含分片键的某些查询可能仍会导致广播操作,具体取决于群集中数据的分布和查询的选择性。
如何mongos处理查询修饰符
排序
如果查询的结果未排序,则mongos 实例将打开结果游标,该游标将对分片上的所有游标进行“轮循”。
Limits
如果查询使用limit()cursor方法限制了结果集的大小 ,则mongos 实例将该限制传递给分片,然后将该限制重新应用于结果,然后再将结果返回给客户端。
Skips
如果查询使用skip()游标方法指定要跳过的记录数,mongos将无法将跳过传递给shard,而是从shard中检索未跳过的结果,并在组装完整结果时跳过适当数量的文档。
当与limit()一起使用时,mongos会将limit加上skip()的值传递给shard,以提高这些操作的效率。
Read Preference 和分片
对于分片群集,从分片读取时,mongos应用 read preference 。所选成员受 read preference 和 replication.localPingThresholdMs设置的支配,并针对每个操作进行重新评估。
Hedged Reads
从版本4.4开始,mongos实例可以对使用非主要读取首选项的读取进行hedged reads。对于hedged reads,mongos实例将读取操作路由到每个查询的shard的两个副本集成员,并返回第一个响应的结果。
Hedged Reads 和 Read Preference
hedged reads是读取首选项的一部分,每个操作都指定了限制读取。非主要读取首选项支持hedged reads。
- 要为非主读取首选项指定限制读取,请参阅驱动程序读取首选项API文档。
- Read preference nearest在默认情况下启用hedged Read选项。
启用/禁用hedged reads
默认情况下,mongos实例支持使用hedged reads。要关闭mongos实例对hedged reads的支持,请参阅readHedgingMode参数。如果hedged reads支持为off,mongos则无论hedge为读取首选项指定了什么选项,都不使用hedged reads。
Targeted Operations vs. Broadcast Operations
通常,分片环境中最快的查询是mongos使用分片键和配置服务器中的群集元数据路由到单个分片的查询 。这些目标操作使用分片键值来定位满足查询文档的分片或分片子集。
对于不包含分mongos片键的查询,必须查询所有分片,等待它们的响应,然后将结果返回给应用程序。这些“分散/聚集”查询可能是长时间运行的操作。
Broadcast Operations
Targeted Operations
索引使用
如果查询不包含分片键,则 mongos必须将查询作为“分散/聚集”操作发送给所有分片。每个shard都会反过来,使用任何的碎片关键指标或其他更有效的指标来满足查询。
如果查询包含引用由分片键和辅助索引索引的字段的多个子表达式,则 mongos可以将查询路由到特定分片,并且分片将使用使它最有效地执行的索引。
其他
FCV兼容性
从MongoDB 4.0开始,mongos尝试连接功能兼容版本(fCV)大于的mongod实例 时,二进制文件将崩溃。例如,您不能将fCV设置为4.2的MongoDB 4.0版本连接到4.2分片群集。但是,您可以将MongoDB 4.0版本连接 到fCV设置为4.0的4.2分片群集。mongosmongosmongos
连接池
从MongoDB 4.2开始,MongoDB添加了参数 ShardingTaskExecutorPoolReplicaSetMatching。此参数确定mongod/mongos实例到分片群集的每个成员的连接池的最小大小 。该值在运行时可能会有所不同。
mongod并mongos维护分片群集中每个副本集的每个副本集的连接池。默认情况下,这些池的连接数至少是与主数据库的连接数。
要进行修改,请参见ShardingTaskExecutorPoolReplicaSetMatching。
分片群集安全性
使用内部/成员身份验证可以加强集群内部的安全性,并防止未经授权的集群组件访问集群。您必须mongod使用适当的安全设置启动集群中的每个服务器,以强制执行内部身份验证。
分片键
MongoDB使用分片键在各个分片之间分发collection的文档。分片键由文档中的一个或多个字段组成。
- 从版本4.4开始,分片集合中的文档可能缺少分片键字段。在跨分片分布文档时,缺少分片键字段将被视为具有空值,但在路由查询时则不会。有关更多信息,请参见 Missing Shard Key。
- 在4.2版及更早版本中,分片集合中的每个文档中都必须存在分片键字段。
在分片集合时选择分片键。
- 从MongoDB 4.4开始,您可以通过向现有键中添加一个或多个后缀字段来优化集合的分片键。有关refineCollectionShardKey详细信息,请参见 。
- 在MongoDB 4.2和更低版本中,无法在分片后更改分片键的选择。
文档的分片键值决定了其在各个分片中的分布。
- 从MongoDB 4.2开始,您可以更新文档的分片键值,除非您的分片键字段为不可变_id字段。有关更多信息,请参见 更改文档的分片键值。
- 在MongoDB 4.0和更早版本中,文档的分片键字段值是不可变的。
分片索引
要对已填充的集合进行分片,该集合必须具有以分片键开头的 索引。分片一个空集合时,如果该集合还没有针对指定分片键的适当索引,则MongoDB会创建支持索引。
分片键策略
分片键的选择会影响分片群集的性能,效率和可伸缩性。选择分片键可以使具有最佳硬件和基础结构的群集成为瓶颈。分片键及其索引的选择也会影响群集可以使用的分片策略。
块(Chunks)
MongoDB的分区分片数据分成块。每个分块都有一个基于分片键的上下限范围 。
均衡器(Balancer )和块分布
为了在整个集群中的所有分片上实现块的均匀分布,平衡器在后台运行,以在各分片上迁移块。
拆分的优势
读/写
MongoDB将读写工作负载分布在分片集群中的各个分 片上,从而允许每个分片处理集群操作的子集。通过添加更多分片,可以在集群中水平扩展读写工作负载。
对于包含分片关键字或复合分片关键字的前缀mongos的查询,可以将查询定位到特定的分片或一组分片。这些目标操作通常比广播到群集中的每个分片更有效 。
从MongoDB 4.4开始,mongos可以支持hedged reads 以最大程度地减少延迟。
存储容量
分片横跨分发数据碎片在集群中,允许每个碎片以包含总簇数据的子集。随着数据集的增长,其他分片将增加群集的存储容量。
高可用性
将配置服务器和分片作为副本集进行部署可提高可用性。
即使一个或多个分片副本集变得完全不可用,分片群集也可以继续执行部分读取和写入操作。也就是说,虽然无法访问不可用分片上的数据,但是针对可用分片的读取或写入仍然可以成功。
分片前的注意事项
分片式群集基础结构的要求和复杂性要求仔细计划,执行和维护。
分片后,MongoDB不会提供任何方法来取消分片。
为了确保群集的性能和效率,在选择分片密钥时需要仔细考虑。
分片有一定的操作要求和限制。
如果查询不包含分片键或复合分片键的前缀 ,请mongos执行广播操作,查询分 片群集中的所有分片。这些分散/聚集查询可能是长时间运行的操作。
分片和非分片集合
数据库可以包含分片和未分片集合的混合。分片集合在群集中的分片上分区和分布 。未分片的集合存储在 主分片上。每个数据库都有其自己的主碎片。
连接到分片群集
您必须连接到mongos路由器才能与分片群集中的任何集合进行交互。这包括分片和未分片的集合。客户端永远不要连接到单个分片以执行读取或写入操作。
分片策略
MongoDB支持两种分片策略,用于在分片群集之间分布数据。
哈希分片
哈希分片涉及计算分片键字段值的哈希值。然后,根据散列的分片键值为每个块分配一个范围。
建议
使用哈希索引解析查询时,MongoDB自动计算哈希值。应用程序也不会需要计算哈希值。
尽管一系列分片键可能是“接近”的,但它们的散列值不太可能在同一块上。基于散列值的数据分发有助于更均匀的数据分发,尤其是在分片键单调更改的数据集中。
但是,散列分布意味着对分片键的基于范围的查询不太可能针对单个分片,从而导致更多的群集范围 广播操作
范围(range)分片
远程分片涉及根据分片键值将数据划分为多个范围。然后,根据分片键值为每个块分配一个范围。
值为“ close”的一系列分片键更有可能驻留在同一块上。这允许有针对性的操作,因为mongos可以将操作仅路由到包含所需数据的分片。
远程分片的效率取决于选择的分片键。分片密钥考虑不周全会导致数据分布不均,这可能会削弱分片的某些优势或导致性能瓶颈。
分片群集中的Zones
Zones 可以帮助改进跨多个数据中心的分片集群的数据位置。
在分片群集中,您可以基于shard key创建分片数据Zones 。您可以将每个Zones 与集群中的一个或多个分片关联。分片可以与任意数量的区域关联。在平衡的集群中,MongoDB仅将Zones 覆盖的块迁移到与该区域关联的碎片。
每个Zones 覆盖一个或多个分片键值范围。区域覆盖的每个范围始终包括其下边界和上边界。
在定义要覆盖的Zones 的新范围时,必须使用分片键中包含的字段。如果使用复合分片键,则范围必须包含分片键的前缀。有关更多信息,请参见区域中的分片键。
选择分片键时,应考虑将来可能使用的区域。
建议
从MongoDB 4.0.3开始,在 对空集合或不存在的集合进行分片之前设置区域和区域范围可以更快地设置区域分片。
分片中的排序规则
使用shardCollection命令和排序规则:{locale:“simple”}选项来切分具有默认排序规则的集合。成功的分片需要:
- 集合必须有一个索引,该索引的前缀是分片键
- 索引必须具有排序规则 { locale: "simple" }
使用排序规则创建新集合时,请在分片集合之前确保满足这些条件。
注意:对分片集合的查询继续使用为集合配置的默认排序规则。要使用shard key索引的简单排序规则,请在查询的排序规则文档中指定{locale:“simple”}。
- 点赞
- 收藏
- 关注作者
评论(0)