我们有一个相对简单的分片MongoDB设置:4个分片,每个分片是一个副本集,至少有3个成员。每个集合包含从许多文件加载的数据;每个文件都有一个单调递增的ID,并且基于ID的散列完成分片。
我们的大部分系列都按预期工作。但是,我有一个集合,似乎没有正确分布跨分片的块。在创建索引之前,该集合已经加载了大约30GB的数据并且它被分片,但是就我所知,这应该不重要。以下是该集合的统计数据:
mongos> db.mycollection.stats()
{
"sharded" : true,
"ns" : "prod.mycollection",
"count" : 53304954,
"numExtents" : 37,
"size" : 35871987376,
"storageSize" : 38563958544,
"totalIndexSize" : 8955712416,
"indexSizes" : {
"_id_" : 1581720784,
"customer_code_1" : 1293148864,
"job_id_1_customer_code_1" : 1800853936,
"job_id_hashed" : 3365576816,
"network_code_1" : 914412016
},
"avgObjSize" : 672.9578525853339,
"nindexes" : 5,
"nchunks" : 105,
"shards" : {
"rs0" : {
"ns" : "prod.mycollection",
"count" : 53304954,
"size" : 35871987376,
"avgObjSize" : 672.9578525853339,
"storageSize" : 38563958544,
"numExtents" : 37,
"nindexes" : 5,
"lastExtentSize" : 2146426864,
"paddingFactor" : 1.0000000000050822,
"systemFlags" : 0,
"userFlags" : 0,
"totalIndexSize" : 8955712416,
"indexSizes" : {
"_id_" : 1581720784,
"job_id_1_customer_code_1" : 1800853936,
"customer_code_1" : 1293148864,
"network_code_1" : 914412016,
"job_id_hashed" : 3365576816
},
"ok" : 1
}
},
"ok" : 1
}
这个集合的sh.status():
prod.mycollection
shard key: { "job_id" : "hashed" }
chunks:
rs0 105
too many chunks to print, use verbose if you want to force print
为什么这个集合只会分发到rs0,我有什么遗漏?有没有办法强制重新平衡?我执行了相同的步骤来分片其他集合,并且它们正确地分发了自己。以下是成功分片的集合的统计信息:
mongos> db.myshardedcollection.stats()
{
"sharded" : true,
"ns" : "prod.myshardedcollection",
"count" : 5112395,
"numExtents" : 71,
"size" : 4004895600,
"storageSize" : 8009994240,
"totalIndexSize" : 881577200,
"indexSizes" : {
"_id_" : 250700688,
"customer_code_1" : 126278320,
"job_id_1_customer_code_1" : 257445888,
"job_id_hashed" : 247152304
},
"avgObjSize" : 783.3697513591966,
"nindexes" : 4,
"nchunks" : 102,
"shards" : {
"rs0" : {
"ns" : "prod.myshardedcollection",
"count" : 1284540,
"size" : 969459424,
"avgObjSize" : 754.7133012595949,
"storageSize" : 4707762176,
"numExtents" : 21,
"nindexes" : 4,
"lastExtentSize" : 1229475840,
"paddingFactor" : 1.0000000000000746,
"systemFlags" : 0,
"userFlags" : 0,
"totalIndexSize" : 190549856,
"indexSizes" : {
"_id_" : 37928464,
"job_id_1_customer_code_1" : 39825296,
"customer_code_1" : 33734176,
"job_id_hashed" : 79061920
},
"ok" : 1
},
"rs1" : {
"ns" : "prod.myshardedcollection",
"count" : 1287243,
"size" : 1035438960,
"avgObjSize" : 804.384999568846,
"storageSize" : 1178923008,
"numExtents" : 17,
"nindexes" : 4,
"lastExtentSize" : 313208832,
"paddingFactor" : 1,
"systemFlags" : 0,
"userFlags" : 0,
"totalIndexSize" : 222681536,
"indexSizes" : {
"_id_" : 67787216,
"job_id_1_customer_code_1" : 67345712,
"customer_code_1" : 30169440,
"job_id_hashed" : 57379168
},
"ok" : 1
},
"rs2" : {
"ns" : "prod.myshardedcollection",
"count" : 1131411,
"size" : 912549232,
"avgObjSize" : 806.5585644827565,
"storageSize" : 944386048,
"numExtents" : 16,
"nindexes" : 4,
"lastExtentSize" : 253087744,
"paddingFactor" : 1,
"systemFlags" : 0,
"userFlags" : 0,
"totalIndexSize" : 213009328,
"indexSizes" : {
"_id_" : 64999200,
"job_id_1_customer_code_1" : 67836272,
"customer_code_1" : 26522944,
"job_id_hashed" : 53650912
},
"ok" : 1
},
"rs3" : {
"ns" : "prod.myshardedcollection",
"count" : 1409201,
"size" : 1087447984,
"avgObjSize" : 771.6769885914075,
"storageSize" : 1178923008,
"numExtents" : 17,
"nindexes" : 4,
"lastExtentSize" : 313208832,
"paddingFactor" : 1,
"systemFlags" : 0,
"userFlags" : 0,
"totalIndexSize" : 255336480,
"indexSizes" : {
"_id_" : 79985808,
"job_id_1_customer_code_1" : 82438608,
"customer_code_1" : 35851760,
"job_id_hashed" : 57060304
},
"ok" : 1
}
},
"ok" : 1
}
sh.status()用于正确分片的集合:
prod.myshardedcollection
shard key: { "job_id" : "hashed" }
chunks:
rs2 25
rs1 26
rs3 25
rs0 26
too many chunks to print, use verbose if you want to force print
答案 0 :(得分:12)
在MongoDB中,当你进入分片系统而你没有看到任何平衡时,它可能是其中的一件事。
您可能没有足够的数据来触发平衡。这绝对不是你的情况,但有些人可能没有意识到,默认的块大小为64MB,可能需要一段时间才能插入数据,然后才能将其中的一些分割并平衡到其他块。
平衡器可能没有运行 - 因为你的其他系列在你的情况下不太可能达到平衡,除非这个系列在平衡器由于某种原因停止后最后被分割。
您的收藏中的数据块无法移动。当分片键不够精细以将数据分成足够小的块时,就会发生这种情况。事实证明这是你的情况,因为你的分片键对于这个大型集合来说不够精细 - 你有105个块(可能对应于唯一的job_id值的数量)和超过30GB的数据。当块太大而且平衡器无法移动它时,它会将它们标记为“巨型”(因此它不会旋转它们的轮子试图移动它们)。
如何从糟糕的碎片选择中恢复?通常,更改分片键非常痛苦 - 因为分片键是不可变的,您必须执行相当于完整数据迁移才能将其转换为具有另一个分片键的集合。但是,在你的情况下,集合仍然在一个碎片上,因此它应该相对容易“unshard”集合并使用新的分片键重新设置它。因为job_id的数量相对较小,所以我建议在job_id,customer_code上使用常规索引进行分片,因为你可能会查询它,我猜它总是在文档创建时设置。