关于此任务
重要
Atlas Infinite 集群不支持此功能。
警告
避免同时执行滚动索引和复制索引构建过程,因为这可能会导致意外问题,例如构建中断和循环崩溃。
Considerations
Unique Indexes
要通过以下过程创建唯一索引,必须在此过程中停止对集合的所有写入。
如果您在执行步骤的过程中无法停止所有对集合的写入操作,请不要使用本页所列的步骤。相反,通过在分片集群的 mongos 上发出db.collection.createIndex() 来为集合构建唯一索引。
Oplog 大小
确保您的 oplog 足够大,以允许索引或重新索引操作完成,而不会落后太远而无法赶上。有关更多信息,请参阅 oplog 大小调整文档。
滚动索引构建会降低集群的弹性并增加构建持续时间。
先决条件
- 用于构建唯一索引
要使用以下过程创建唯一索引,您必须在索引构建期间停止对集合的所有写入。否则,可能在副本集节点之间具有不一致的数据。如果您无法停止对集合的所有写入,请不要使用以下过程创建唯一索引。
警告
如果无法停止对集合的所有写入,请勿使用以下步骤创建唯一索引。
在创建索引之前,请验证集合中是否有任何文档违反索引约束。 如果集合分布在分片上,并且分片包含具有重复文档的数据段,则创建索引操作可能会在没有重复项的分片上成功,但不会在有重复项的分片上成功。 为避免分片之间留下不一致的索引,您可以发出
db.collection.dropIndex()中的mongos将索引从集合中删除。
步骤
A. 停止负载均衡器
Connect mongosh to a mongos instance in the sharded cluster, and run sh.stopBalancer() to disable the balancer: [1]
sh.stopBalancer()
注意
如果迁移正在进行,系统将在停止负载均衡器之前完成进行中的迁移。
要验证是否禁用了负载均衡器,请运行 sh.getBalancerState();如果已禁用负载均衡器,则会返回 false:
sh.getBalancerState()
| [1] | 从 MongoDB 6.0.3 开始,不再执行自动数据块分割。这是因为均衡策略的改进。自动分割命令仍然存在,但不执行操作。 在 6.0.3 之前的 MongoDB 版本中, |
B. 确定集合的分配情况
From mongosh connected to the mongos, refresh the cached routing table for that mongos to avoid returning stale distribution information for the collection. Once refreshed, run db.collection.getShardDistribution() for the collection you wish to build the index.
例如,如果您要在 test 数据库中的 records 集合上创建升序索引:
db.adminCommand( { flushRouterConfig: "test.records" } ); db.records.getShardDistribution();
该方法输出分片分配。例如,考虑一个具有 3 个分片(shardA、shardB 和 shardC)的分片集群,db.collection.getShardDistribution() 返回以下内容:
Shard shardA at shardA/s1-mongo1.example.net:27018,s1-mongo2.example.net:27018,s1-mongo3.example.net:27018 data : 1KiB docs : 50 chunks : 1 estimated data per chunk : 1KiB estimated docs per chunk : 50 Shard shardC at shardC/s3-mongo1.example.net:27018,s3-mongo2.example.net:27018,s3-mongo3.example.net:27018 data : 1KiB docs : 50 chunks : 1 estimated data per chunk : 1KiB estimated docs per chunk : 50 Totals data : 3KiB docs : 100 chunks : 2 Shard shardA contains 50% data, 50% docs in cluster, avg obj size on shard : 40B Shard shardC contains 50% data, 50% docs in cluster, avg obj size on shard : 40B
根据输出,您只能在 shardA 和 shardC 上构建 test.records 的索引。
C. 在包含集合数据块的分片上构建索引
对于包含集合数据段的每个分片,请按照在分片上构建索引的过程进行操作。
C1. 停止一个从节点并重启为独立实例
对于受影响的分片,停止与其从节点之一关联的 mongod 进程。在进行以下配置更新后,重新启动:
如果使用配置文件,请进行以下配置更新:
注释掉
replication.replSetName选项。注释掉
sharding.clusterRole选项。在
setParameter部分中将参数skipShardingConfigurationChecks设置为true。在
setParameter部分中将参数disableLogicalSessionCacheRefresh设置为true。
例如,对于分片副本集节点,更新后的配置文件将包含类似如下示例的内容:
net: bindIp: localhost,<hostname(s)|ip address(es)> port: 27218 # port: 27018 #replication: # replSetName: shardA #sharding: # clusterRole: shardsvr setParameter: skipShardingConfigurationChecks: true disableLogicalSessionCacheRefresh: true
并重新启动:
mongod --config <path/To/ConfigFile>
其他设置(例如storage.dbPath 等等)保持不变。
如果使用命令行选项,请进行以下配置更新:
如果是分片成员,则删除
--shardsvr;如果是配置服务器分片,则删除 {--configsvr。在
--setParameter选项中将参数 设置为skipShardingConfigurationChecks。true在
--setParameter选项中将参数disableLogicalSessionCacheRefresh设置为true。
例如,在不使用 --replSet 和 --shardsvr 选项的情况下重启分片副本集节点。指定新的端口号并将 skipShardingConfigurationChecks 和 disableLogicalSessionCacheRefresh 参数均设置为 true:
mongod --port 27218 --setParameter skipShardingConfigurationChecks=true --setParameter disableLogicalSessionCacheRefresh=true
其他设置(例如--dbpath 等等)保持不变。
| [2] | (1, 2) By running the mongod on a different port, you ensure that the other members of the replica set and all clients will not contact the member while you are building the index. |
C2. 构建索引
直接连接到在新端口上独立运行的 mongod 实例,并为该实例创建新索引。
For example, connect mongosh to the instance, and use the db.collection.createIndex() method to create an ascending index on the username field of the records collection:
db.records.createIndex( { username: 1 } )
C3。以副本集节点身份重新启动程序 mongod
索引构建完成后,关闭 mongod 实例。撤消以独立节点身份启动时所做的配置更改,以恢复其原始配置,并重新启动。
重要
请务必删除 skipShardingConfigurationChecks 和 disableLogicalSessionCacheRefresh 参数。
例如,要重新启动副本集分片成员:
如果您在使用配置文件:
恢复到原始端口号。
取消对
replication.replSetName的注释。取消对
sharding.clusterRole的注释。移除
setParameter部分中的参数skipShardingConfigurationChecks。删除
setParameter部分的参数disableLogicalSessionCacheRefresh。
net: bindIp: localhost,<hostname(s)|ip address(es)> port: 27018 replication: replSetName: shardA sharding: clusterRole: shardsvr
其他设置(例如storage.dbPath 等等)保持不变。
并重新启动:
mongod --config <path/To/ConfigFile>
如果您使用的是命令行选项:
恢复到原始端口号。
包括
--replSet。如果是分块节点,请包含
--shardsvr;如果是配置服务器节点,请包含--configsvr。Remove parameter
skipShardingConfigurationChecks.Remove parameter
disableLogicalSessionCacheRefresh.
例如:
mongod --port 27018 --replSet shardA --shardsvr
其他设置(例如--dbpath 等等)保持不变。
允许复制赶上此节点。
C4. 对分片的剩余从节点重复该过程
一旦该节点赶上副本集中的其他节点,逐次逐个对剩余从节点重复该过程:
E. 在主节点上构建索引
当分片的所有从节点均有新索引时,分片的主节点降级,通过上述过程将其重启为独立运行的节点,然后在前一个主节点上构建索引:
Use the
rs.stepDown()method inmongoshto step down the primary. Upon successful stepdown, the current primary becomes a secondary and the replica set members elect a new primary.
D. 对其他受影响的分片重复上述步骤
在完成构建分片的索引后,为其他受影响的分片重复执行 C. 在包含集合数据块的分片上构建索引。
E. 重新启动负载均衡器
在完成受影响的分片的滚动索引构建后,重新启动负载均衡器。
Connect mongosh to a mongos instance in the sharded cluster, and run sh.startBalancer(): [3]
sh.startBalancer()
| [3] | 从 MongoDB 6.0.3 开始,不再执行自动数据块分割。这是因为均衡策略的改进。自动分割命令仍然存在,但不执行操作。 在 6.0.3 之前的 MongoDB 版本中, |
更多信息
如果一个分片集合在包含集合数据块的每个分片上没有完全相同的索引(包括索引选项),则该集合的索引不一致。尽管一般操作过程中不应出现索引不一致的情况,但这种情况仍有可能发生,例如:
当用户使用
unique键约束创建索引,且一个分片包含具有重复文档的数据段时。在此类情况下,创建索引操作可能会对没有重复项的分片成功完成,而对有重复项的分片失败。当用户以滚动方式跨分片创建索引,但未能为关联分片构建索引或错误地构建了具有不同规范的索引。
配置服务器主节点会定期检查分片集合的分片之间的索引不一致情况。要配置这些定期检查,请参阅 enableShardedIndexConsistencyCheck 和 shardedIndexConsistencyCheckIntervalMS。
在配置服务器主节点上运行时,命令 serverStatus 返回字段 shardedIndexConsistency 以报告索引不一致的情况。
要检查分片集合是否存在不一致的索引,请参阅查找分片间不一致的索引。