【问题标题】:Default range shard key mongodb默认范围分片键 mongodb
【发布时间】:2014-11-06 03:53:29
【问题描述】:

我有一个带有 2 个分片(比如说 A 和 B)的 mongodb 分片,每个分片有 17GB 可用空间。我将包含对象 ID 的 _id 设置为分片键。

以下是用于设置 db 和 collection 的命令。

sh.enableSharding("testShard");
sh.shardCollection("testShard.shardedCollection", {_id:1});

然后我尝试向 mongos 服务器发起 4,000,000 个插入查询。我执行脚本低于 4 次。

for(var i=0; i<1000000; i++){
  db.shardedCollection.insert({x:i});
}

使用 _id 作为分片键,据我了解,上述 4000000 个文档将适合 1 个分片,所有插入将仅发生在 A 分片中。

然而,结果并不像我预期的那样,在 A 分片中插入了约 130 万份文档,在 B 分片中插入了另外约 270 万份文档。

为什么会这样? shard coll 设置命令中是否缺少某些内容?还是我的理解有误,可能mongodb中有default range shard key之类的东西?

如果有人可以分享默认范围分片键的行为(不知道标签),那将非常有帮助。

下面是 sh.status() 结果

  shard key: { "_id" : 1 }
  chunks:
    B  5
    A  5
  { "_id" : { "$minKey" : 1 } } -->> { "_id" : ObjectId("540c703398c7efdea6037cbc") } on : B Timestamp(6, 0) 
  { "_id" : ObjectId("540c703398c7efdea6037cbc") } -->> { "_id" : ObjectId("540c703498c7efdea603bfe3") } on : A Timestamp(6, 1) 
  { "_id" : ObjectId("540c703498c7efdea603bfe3") } -->> { "_id" : ObjectId("540c704398c7efdea605d818") } on : A Timestamp(3, 0) 
  { "_id" : ObjectId("540c704398c7efdea605d818") } -->> { "_id" : ObjectId("540c705298c7efdea607f04e") } on : A Timestamp(4, 0) 
  { "_id" : ObjectId("540c705298c7efdea607f04e") } -->> { "_id" : ObjectId("540c707098c7efdea60c20ba") } on : B Timestamp(5, 1) 
  { "_id" : ObjectId("540c707098c7efdea60c20ba") } -->> { "_id" : ObjectId("540c7144319c0dbee096f7d6") } on : B Timestamp(2, 4) 
  { "_id" : ObjectId("540c7144319c0dbee096f7d6") } -->> { "_id" : ObjectId("540c7183319c0dbee09f58ad") } on : B Timestamp(2, 6) 
  { "_id" : ObjectId("540c7183319c0dbee09f58ad") } -->> { "_id" : ObjectId("540eb15ddace5b39fbc32239") } on : B Timestamp(4, 2) 
  { "_id" : ObjectId("540eb15ddace5b39fbc32239") } -->> { "_id" : ObjectId("540eb192dace5b39fbca8a84") } on : A Timestamp(5, 2) 
  { "_id" : ObjectId("540eb192dace5b39fbca8a84") } -->> { "_id" : { "$maxKey" : 1 } } on : A Timestamp(5, 3) 

【问题讨论】:

    标签: mongodb sharding


    【解决方案1】:

    正如@LalitAgarwal 已经指出的那样,ObjectIds 默认情况下会生成错误的分片键。但是,如果您并不真正关心您的数据位于哪个分片,而只想让写入操作和块在您的分片之间均匀分布,那么这很容易获得:

    db.shardedCollection.ensureIndex({_id:"hashed"});
    sh.enableSharding("testShard");
    sh.shardCollection("testShard.shardedCollection", {_id:"hashed"});
    

    但是,这会带来一些(通常可以忽略不计)缺点:

    1. 您有一个附加索引仅用于分片,没有其他用例
    2. 此索引会占用一些 RAM,这是高负载生产节点上的宝贵资源
    3. 此人工索引在插入期间需要写入操作

    更好的方法是找到非人工分片键。详情请阅读Considerations for Selecting Shard Keys。简而言之:

    1. 找到一个字段或字段组合,可以明确标识每个文档(组合)彼此之间存在很大差异。理想情况下,这些都应该是您查询的字段。
    2. 将此字段或字段组合用作您的_id。由于 _id 字段无论如何都需要索引,并且您查询这些字段,因此您摆脱了不需要的索引。
    3. 使用选定的 _id 字段作为您的分片键。

    【讨论】:

    • 我会按objectId顺序读取文档。因此,我认为牺牲 1 个分片的写入是个好主意,但是当我想按顺序读取时,它也会被本地化为 1 个分片。
    • 不,它不会,因为平衡器迟早会启动。 ;)
    【解决方案2】:

    是的,你是对的,它应该进入单个分片。但是,虽然在单个分片上进行插入,但平衡器也会平衡分片并将块移动到其他分片。

    话虽如此,您应该做的是通过从您的 mongos 调用以下命令来停止/禁用平衡器。

    http://docs.mongodb.org/manual/reference/method/sh.disableBalancing/#sh.disableBalancing

    sh.disableBalancing(namespace)
    //namespace     string  The namespace of the collection.
    

    完成后,开始插入并查看所有插入的去向。

    对于 _id 字段分片,你也可以看这里:

    http://docs.mongodb.org/manual/faq/sharding/#can-you-shard-on-the-id-field

    Be aware that ObjectId() values, which are the default value of the _id field, 
    increment as a timestamp. As a result, when used as a shard key, all new documents
    inserted into the collection will initially belong to the same chunk on a single 
    shard. Although the system will eventually divide this chunk and migrate its contents 
    to distribute data more evenly, at any moment the cluster can only direct insert 
    operations at a single shard. This can limit the throughput of inserts. If most of 
    your write operations are updates, this limitation should not impact your performance. 
    However, if you have a high insert volume, this may be a limitation.
    

    【讨论】:

    • 当 balancer 被禁用时,如果第一个 shard 已满,是否会继续向下一个 shard 写入文档?
    • 我认为没有。对于 mongos 写入任何特定分片,该特定块范围需要存在于该分片中。禁用平衡器后,您将不会有任何块到下一个分片。为了使它成为可能,您必须手动拆分块并将其移动到另一个分片,然后 mongos 将开始将数据放入另一个分片。
    猜你喜欢
    • 1970-01-01
    • 2011-09-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-30
    • 1970-01-01
    • 2018-09-15
    相关资源
    最近更新 更多