代码改变世界

在 MongoDB 分片集群上检查索引的一致性

  abce  阅读(51)  评论(0编辑  收藏  举报

 

在 MongoDB 分片集群中,各分片之间索引分布不一致的情况比你想象的要常见,这是因为用户不使用 MongoS 而是直接在分片中创建索引。

 

在块迁移过程中,由于索引不匹配,系统无法在分片间传输数据,从而导致迁移失败。

 

发生这种情况时,分片日志中的典型错误信息可能如下所示:

1
2
3
4
5
{"t":{"$date":"2024-05-23T14:27:49.111+00:00"},"s":"I", "c":"SHARDING", "id":5087102, "ctx":"migrateThread",
"msg":"Recipient failed to copy oplog entries for retryable writes and transactions from donor","attr":
{"namespace":"test.cincomillones","migrationSessionId":"Shard_1_Shard_2_646884t4835b68a1af8781","fromShard":
"Shard_1","error":"migrate failed: CannotCreateCollection: aborting, shard is missing 1 indexes and collection
is not empty. Non-trivial index creation should be scheduled manually"}}

该错误表明,由于一个或多个分片上的索引缺失,无法迁移块。要解决这个问题,必须确保所有分片的索引一致性。

 

检查和解决此问题的步骤:

第一步是连接到每个分片的 PRIMARY 节点,检查有问题的集合的索引。在本示例中,正如我们在日志文件中看到的,集合 test.cincomillones 存在索引不一致问题。

 

以 PRIMARY 分片为参考,检查索引在哪个分区丢失是非常重要的。

分片1:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
shard1:PRIMARY> db.cincomillones.getIndexes()
[
    {
        "v": 2,
        "key": {
            "_id": 1
        },
        "name": "_id_"
    },
    {
        "v": 2,
        "key": {
            "BetID": "hashed"
        },
        "name": "BetID_hashed"
    },
    {
        "v": 2,
        "key": {
            "MasterEventId": 1
        },
        "name": "MasterEventId_1"
    }
]

分片2:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
shard2:PRIMARY> db.cincomillones.getIndexes()
[
    {
        "v": 2,
        "key": {
            "_id": 1
        },
        "name": "_id_"
    },
    {
        "v": 2,
        "key": {
            "BetID": "hashed"
        },
        "name": "BetID_hashed"
    }
]

如上所示,与分片 2 相比,分片 1 多了一个索引(MasterEventId_1)。索引不匹配导致了块迁移失败。

 

要解决这个问题,我们需要在缺少索引的分片上创建缺少的索引。在这种情况下,我们将在分片 2 中添加 MasterEventId 索引:

1
shard2:PRIMARY> db.cincomillones.createIndex({ "MasterEventId": 1 })

创建缺失索引后,一个好的做法是验证所有分片的索引是否一致。

 

我们可以在所有分片上再次运行 getIndexes,或者使用 MongoDB 内置命令 shardedIndexConsistency 来检查。

 

你需要在 PRIMARY configServer 上运行以下命令来检查分片间的索引不一致性:

1
config:PRIMARY> db.serverStatus().shardedIndexConsistency

该命令将报告任何不一致,从而确保所有分片保持同步。

 

创建丢失的索引后,我们将不再看到有索引不一致:

1
2
3
configRepl:PRIMARY> db.serverStatus().shardedIndexConsistency
 
{ "numShardedCollectionsWithInconsistentIndexes" : NumberLong(0) }

 

如果运行的是 MongoDB 5.0,则可以使用聚合管道来查找分片间不一致的索引,如下所述:

1
https://www.mongodb.com/docs/v5.0/tutorial/manage-indexes/#find-inconsistent-indexes-across-shards

 

从 MongoDB 7.0 开始,可以使用一项新功能来检查不一致索引:

1
https://www.mongodb.com/docs/manual/reference/inconsistency-type/InconsistentIndex/

该方法会返回一个游标,其中包含一批文档,显示在分片元数据中发现的不一致之处,即

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
{
  cursor: {
     id: Long("0"),
     ns: "test.$cmd.aggregate",
     firstBatch: [
        {
           type: "InconsistentIndex",
           description: "Found an index of a sharded collection that is inconsistent between different shards",
           details: {
              namespace: "test.authors",
              info: {
                  missingFromShards: [
                     "shard-rs1"
                  ],
                  inconsistentProperties: [ ],
                  indexName: "index1"
              }
           }
        }
     ],
  },
  ok: 1
}

确保分片间的索引一致性对于 MongoDB 分片集群的顺利运行至关重要。不一致的索引可能会阻碍块迁移,从而导致潜在的停机或性能下降。

 

通过检查每个分片的索引、修复不匹配并使用所述方法验证一致性,可以保持集群平稳运行。

 

有关索引一致性检查的更多详情,请参阅 MongoDB 的官方文档:

1
2
3
4
5
https://www.mongodb.com/docs/v5.0/reference/command/serverStatus/#mongodb-serverstatus-serverstatus.shardedIndexConsistency
 
https://www.mongodb.com/docs/v5.0/tutorial/manage-indexes/#find-inconsistent-indexes-across-shards
 
https://www.mongodb.com/docs/manual/reference/inconsistency-type/InconsistentIndex/
相关博文:
阅读排行:
· DeepSeek “源神”启动!「GitHub 热点速览」
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 我与微信审核的“相爱相杀”看个人小程序副业
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)
· spring官宣接入deepseek,真的太香了~
历史上的今天:
2020-12-10 Oracle使用audit跟踪登录失败的连接信息
2015-12-10 threaded_execution
2015-12-10 数据块损坏(block corruption)
点击右上角即可分享
微信分享提示