Docs HomeMongoDB Manual

Reshard a Collection重新分片集合

New in version 5.0. 5.0版新增。

The ideal shard key allows MongoDB to distribute documents evenly throughout the cluster while facilitating common query patterns. 理想的分片键允许MongoDB在集群中均匀地分布文档,同时促进常见的查询模式。A suboptimal shard key can lead to performance or scaling issues due to uneven data distribution. 由于数据分布不均匀,次优的分片键可能会导致性能或扩展问题。Starting in MongoDB 5.0, you can change the shard key for a collection to change the distribution of your data across a cluster.从MongoDB 5.0开始,您可以更改集合的分片键,以更改数据在集群中的分布。

Note

Before resharding your collection, read Troubleshoot Shard Keys for information on common performance and scaling issues and advice on how to fix them.在重新分片您的集合之前,请阅读分片键疑难解答,了解有关常见性能和扩展问题的信息以及如何解决这些问题的建议。

Requirements要求

Before you reshard your collection, ensure that you meet the following requirements:在重新分片之前,请确保您满足以下要求:

  • Your application can tolerate a period of two seconds where the collection that is being resharded blocks writes. 您的应用程序可以容忍两秒钟的时间,在这段时间内,正在被重新分片的集合将阻止写入。During the time period where writes are blocked your application experiences an increase in latency. 在写入被阻止的时间段内,应用程序的延迟会增加。If your workload cannot tolerate this requirement, consider refining your shard key instead.如果您的工作负载不能满足此要求,请考虑再精细化您的分片键
  • Your database meets these resource requirements:您的数据库满足以下资源要求:

    • Available storage space: Ensure that your available storage space is at least 1.2x the size of the collection that you want to reshard. 可用存储空间:确保您的可用存储空间至少是要重新分片的集合大小的1.2倍。For example, if the size of the collection you want to reshard is 1 TB, you should have at least 1.2 TB of free storage when starting the sharding operation.例如,如果要重新分发的集合的大小为1 TB,则在启动分片操作时应至少有1.2 TB的可用存储空间。
    • I/O: Ensure that your I/O capacity is below 50%.I/O:确保您的I/O容量低于50%。
    • CPU load: Ensure your CPU load is below 80%.CPU负载:确保您的CPU负载低于80%。
    Important

    These requirements are not enforced by the database. A failure to allocate enough resources can result in:这些要求不是由数据库强制执行的。未能分配足够的资源可能导致:

    • the database running out of space and shutting down数据库空间不足,正在关闭
    • decreased performance性能下降
    • the resharding operation taking longer than expected重新分拣操作的时间比预期的要长

    If your application has time periods with less traffic, reshard your collection during that time if possible.如果您的应用程序有流量较少的时间段,请尽可能在该时间段内重新分片您的集合。

  • You must perform one of these tasks:您必须执行以下任务之一:

    • rewrite your application's queries to use both the current shard key and the new shard key重写应用程序的查询以同时使用当前的分片键和新的分片键
    • stop your application and then:停止您的应用程序,然后:

      • rewrite your application's queries to use the new shard key重写应用程序的查询以使用新的分片键
      • wait until the resharding of the collection completes (to monitor the resharding process, use a $currentOp pipeline stage)等待集合的重新分片完成(要监视重新分片过程,请使用$currentOp管道阶段)
      • deploy your rewritten application部署重写的应用程序

    The following queries return an error if the query filter does not include both the current shard key or a unique field (like _id):如果查询筛选器不包括当前分片键或唯一字段(如_id),则以下查询将返回错误:

    For optimal performance, we recommend that you also rewrite other queries to include the new shard key.为了获得最佳性能,我们建议您还重写其他查询,以包含新的分片键。

    Once the resharding operation completes, you can remove the old shard key from the queries.一旦重新分片操作完成,就可以从查询中删除旧的分片键。

  • No index builds are in progress. 没有正在进行的索引生成。Use db.currentOp() to check for any running index builds:使用db.currentOp()检查是否有任何正在运行的索引生成:

     db.adminCommand(
    {
    currentOp: true,
    $or: [
    { op: "command", "command.createIndexes": { $exists: true } },
    { op: "none", "msg" : /^Index Build/ }
    ]
    }
    )

    In the result document, if the inprog field value is an empty array, there are no index builds in progress:在结果文档中,如果inprog字段值为空数组,则没有正在进行的索引构建:

    {
    inprog: [],
    ok: 1,
    '$clusterTime': { ... },
    operationTime: <timestamp>
    }
Warning

We strongly recommend that you check the Limitations and read the resharding process section in full before resharding your collection.我们强烈建议您在重新分片集合之前查看限制并完整阅读重新分片过程部分。

Limitations局限性

  • Only one collection can be resharded at a time.一次只能重新分片一个集合。
  • writeConcernMajorityJournalDefault must be true.必须为true
  • Resharding a collection that has a uniqueness constraint is not supported.不支持重新分片具有唯一性约束的集合。
  • The new shard key cannot have a uniqueness constraint.新的分片键不能具有唯一性约束。
  • The following commands and corresponding shell methods are not supported on the collection that is being resharded while the resharding operation is in progress:在进行重新分片操作时,正在重新分片的集合不支持以下命令和相应的shell方法:

  • The following commands and methods are not supported on the cluster while the resharding operation is in progress:在进行重新分片操作时,群集上不支持以下命令和方法:

    Warning

    Using any of the preceding commands during a resharding operation causes the resharding operation to fail.在重新分片操作期间使用任何前面的命令都会导致重新分片操作失败。

  • If the collection to be resharded uses Atlas Search, the search index will become unavailable when the resharding operation completes. 如果要重新分片的集合使用Atlas Search,则当重新分片操作完成时,搜索索引将不可用。You need to manually rebuild the search index once the resharding operation completes.重新分片操作完成后,您需要手动重新生成搜索索引。
  • You can't reshard a sharded time series collection.无法重新分片已分片的时间序列集合

Resharding Process重新分片过程

In a collection resharding operation, a shard can be a:在集合重新分片操作中,分片可以是:

  • donor, which currently stores chunks for the sharded collection.,当前为分片集合存储
  • recipient, which stores new chunks for the sharded collection based on the shard keys and zones.,它基于分片键区域为分片集合存储新的块。

A shard can be donor and a recipient at the same time. 一个分片可以同时是捐赠者和接受者。The set of donor shards is identical to the recipient shards, unless you use zones.供体分片集与受体分片集相同,除非使用区域。

The config server primary is always the resharding coordinator and starts each phase of the resharding operation.配置服务器主服务器始终是重新分片协调器,并启动重新分片操作的每个阶段。

1

Start the resharding operation.开始重新分拣操作。

While connected to the mongos, issue a reshardCollection command that specifies the collection to be resharded and the new shard key:连接到mongos时,发出一个reshardCollection命令,指定要重新分片的集合和新的分片键:

db.adminCommand({
reshardCollection: "<database>.<collection>",
key: <shardkey>
})

MongoDB sets the max number of seconds to block writes to two seconds and begins the resharding operation.MongoDB将阻止写入的最大秒数设置为两秒,并开始重新分片操作。

2

Monitor the resharding operation.监控重新分拣操作。

To monitor the resharding operation, you can use the $currentOp pipeline stage:要监视重新分片操作,可以使用$currentOp管道阶段:

db.getSiblingDB("admin").aggregate([
{ $currentOp: { allUsers: true, localOps: false } },
{
$match: {
type: "op",
"originatingCommand.reshardCollection": "<database>.<collection>"
}
}
])
Note

To see updated values, you need to continuously run the preceeding pipeline.要查看更新的值,您需要连续运行上一个管道。

The $currentOp pipeline outputs:$currentOp管道输出:

  • totalOperationTimeElapsedSecs: elapsed operation time in seconds:运行时间(秒)
  • remainingOperationTimeEstimatedSecs: estimated time remaining in seconds for the current resharding operation. :当前重新分片操作的估计剩余时间(以秒为单位)。It is returned as -1 when a new resharding operation starts.当新的重新分片操作开始时,它将返回为-1

    Starting in:起始时间:

    • MongoDB 5.0, but before MongoDB 6.1, remainingOperationTimeEstimatedSecs is only available on a recipient shard during a resharding operation.MongoDB 5.0,但在MongoDB 6.1之前,remainingOperationTimeEstimatedSecs仅在重新分片操作期间的接收方分片上可用。
    • MongoDB 6.1, remainingOperationTimeEstimatedSecs is also available on the coordinator during a resharding operation.MongoDB 6.1开始,remainingOperationTimeEstimatedSecs也可以在重新分发操作期间在协调器上使用。

    The resharding operation performs these phases in order:重新分拣操作按顺序执行这些阶段:

    1. The clone phase duplicates the current collection data.克隆阶段复制当前集合数据。
    2. The catch-up phase applies any pending write operations to the resharded collection.追赶阶段将任何挂起的写入操作应用于重新分片的集合。

    remainingOperationTimeEstimatedSecs is set to a pessimistic time estimate:设置为悲观的时间估计:

    • The catch-up phase time estimate is set to the clone phase time, which is a relatively long time.追赶阶段时间估计被设置为克隆阶段时间,克隆阶段时间是相对较长的时间。
    • In practice, if there are only a few pending write operations, the actual catch-up phase time is relatively short.在实践中,如果只有几个挂起的写操作,那么实际的追赶阶段时间相对较短。
[
{
shard: '<shard>',
type: 'op',
desc: 'ReshardingRecipientService | ReshardingDonorService | ReshardingCoordinatorService <reshardingUUID>',
op: 'command',
ns: '<database>.<collection>',
originatingCommand: {
reshardCollection: '<database>.<collection>',
key: <shardkey>,
unique: <boolean>,
collation: { locale: 'simple' }
},
totalOperationTimeElapsedSecs: <number>,
remainingOperationTimeEstimatedSecs: <number>,
...
},
...
]
3

Finish the resharding operation.完成重新分拣操作。

Throughout the resharding process, the estimated time to complete the resharding operation (remainingOperationTimeEstimatedSecs) decreases. 在整个重新分拣过程中,完成重新分拣操作的估计时间(remainingOperationTimeEstimatedSecs)会减少。When the estimated time is below two seconds, MongoDB blocks writes and completes the resharding operation. 当估计的时间低于两秒时,MongoDB会阻止写入并完成重新分片操作。Until the estimated time to complete the resharing operation is below two seconds, the resharding operation does not block writes by default. 在完成重新分片操作的估计时间低于两秒之前,默认情况下,重新分片操作不会阻止写入。During the time period where writes are blocked your application experiences an increase in latency.在写入被阻止的时间段内,应用程序的延迟会增加。

Once the resharding process has completed, the resharding command returns ok: 1.一旦重新分片过程完成,重新分片命令将返回ok: 1

{
ok: 1,
'$clusterTime': {
clusterTime: <timestamp>,
signature: {
hash: Binary(Buffer.from("0000000000000000000000000000000000000000", "hex"), 0),
keyId: <number>
}
},
operationTime: <timestamp>
}

To see whether the resharding operation completed successfully, check the output of the sh.status() method:要查看重新分片操作是否成功完成,请检查sh.status()方法的输出:

sh.status()

The sh.status() method output contains a subsection for the databases. sh.status()方法的输出包含databases的一个子部分。If resharding has completed successfully, the output lists the new shard key for the collection:如果重新分片成功完成,输出将列出集合的新分片键:

databases
[
{
database: {
_id: '<database>',
primary: '<shard>',
partitioned: false,
version: {
uuid: <uuid>,
timestamp: <timestamp>,
lastMod: <number>
}
},
collections: {
'<database>.<collection>': {
shardKey: <shardkey>,
unique: <boolean>,
balancing: <boolean>,
chunks: [],
tags: []
}
}
}
...
]
Note

If the resharded collection uses Atlas Search, the search index will become unavailable when the resharding operation completes. 如果重新分片的集合使用Atlas Search,则当重新分片操作完成时,搜索索引将不可用。You need to manually rebuild the search index once the resharding operation completes.重新分片操作完成后,您需要手动重新生成搜索索引。

Block writes early to force resharding to complete提前阻止写入以强制完成重新分片

You can manually force the resharding operation to complete by issuing the commitReshardCollection command. 您可以通过发出commitReshardCollection命令手动强制完成重新分片操作。This is useful if the current time estimate to complete the resharding operation is an acceptable duration for your collection to block writes. 如果完成重新分片操作的当前时间估计值是集合阻止写入的可接受持续时间,则此选项非常有用。The commitReshardCollection command blocks writes early and forces the resharding operation to complete. commitReshardCollection命令会提前阻止写入并强制完成重新分片操作。The command has the following syntax:该命令具有以下语法:

db.adminCommand({
commitReshardCollection: "<database>.<collection>"
})

Abort resharding operation中止重新分片操作

You can abort the resharding operation during any stage of the resharding operation, even after running the commitReshardCollection, until shards have fully caught up.您可以在重新分片操作的任何阶段中止重新分片操作,即使在运行commitReshardCollection之后也是如此,直到分片完全赶上为止。

For example, if the write unavailability duration estimate does not decrease, you can abort the resharding operation with the abortReshardCollection command:例如,如果写入不可用持续时间估计值没有减少,则可以使用abortReshardCollection命令中止重新分片操作:

db.adminCommand({
abortReshardCollection: "<database>.<collection>"
})

After canceling the operation, you can retry the resharding operation during a time window with lower write volume. 取消操作后,您可以在写入量较低的时间窗口内重试重新分片操作。If this is not possible, add more shards before retrying.如果不可能,请在重试之前添加更多分片

Behavior行为

Minimum Duration of a Resharding Operation重新分片操作的最短持续时间

The minimum duration of a resharding operation is always 5 minutes.重新分拣操作的最短持续时间始终为5分钟。

Retryable Writes可重试写入

Retryable writes initiated before or during resharding can be retried during and after the collection has been resharded for up to 5 minutes. 在重新分片之前或期间启动的可重试写入可以在集合重新分片期间和之后重试,最长可达5分钟。After 5 minutes you may be unable to find the definitive result of the write and subsequent attempts to retry the write fail with an IncompleteTransactionHistory error.5分钟后,您可能无法找到写入的最终结果,随后重试写入的尝试将失败,并出现IncompleteTransactionHistory错误。

Error Case错误案例

Duplicate _id Values重复的_id

The resharding operation fails if _id values are not globally unique to avoid corrupting collection data. 如果_id值不是全局唯一的以避免损坏集合数据,则重新分片操作将失败。Duplicate _id values can also prevent successful chunk migration. _id值重复也会阻止块迁移成功。If you have documents with duplicate _id values, copy the data from each into a new document, and then delete the duplicate documents.如果您的文档具有重复的_id值,请将每个文档中的数据复制到一个新文档中,然后删除重复的文档。