分片集群似乎没有基于mongoDB原型上的键来划分数据

时间:2014-11-26 19:30:25

标签: mongodb sharding

背景资料

我定义了以下分片群集:

mongos> sh.status()
--- Sharding Status --- 
  sharding version: {
    "_id" : 1,
    "version" : 4,
    "minCompatibleVersion" : 4,
    "currentVersion" : 5,
    "clusterId" : ObjectId("547496dd009cc54d845c2ff1")
}
  shards:
    {  "_id" : "jjrs0",  "host" : "jjrs0/mongohost1:27017" }
    {  "_id" : "jjrs1",  "host" : "jjrs1/mongohost2:27017" }
    {  "_id" : "jjrs2",  "host" : "jjrs2/mongohost3:27017" }
  databases:
    {  "_id" : "admin",  "partitioned" : false,  "primary" : "config" }
    {  "_id" : "rtables",  "partitioned" : true,  "primary" : "jjrs1" }
        rtables.widgets
            shard key: { "location" : 1, "name" : 1 }
            chunks:
                jjrs1   1
            { "location" : { "$minKey" : 1 }, "name" : { "$minKey" : 1 } } -->> { "location" : { "$maxKey" : 1 }, "name" : { "$maxKey" : 1 } } on : jjrs1 Timestamp(1, 0) 
    {  "_id" : "test",  "partitioned" : false,  "primary" : "jjrs0" }

mongos> 

我有3个replicasets(每个只有一个主要用于测试目的)。 我已将“location”定义为我的分片键,其中location将包含“CAN”表示“Canada”和“USA”表示“United States”的值。 我希望在不同的分片上有不同的位置。

碎片密钥

我做了我认为它的复合键。位置和名称字段构成了关键。小部件的名称将始终是唯一的。

数据/ CSV文件的外观

加拿大CSV文件如下所示:

location,name,rt_id,type
canada,can-widget111,123,the best widget
canada,can-widget222,1,the next best widget

美国CSV看起来像:

location,name,rt_id,type
usa,usa-widget1,24,test widget
usa,usa-widget2,25,widget widget

问题

要么我误解了分片键是如何工作的,要么是我错误地设置了某些东西......或者我可能没有正确验证我的数据。无论如何,这里发生了什么:

  1. 我已将所有加拿大记录导入到“rtables”数据库“jjrs1”的主分片中。这是我跑的命令:
  2.  mongoimport -h mongohost2 --port 27017 -d rtables -c widgets --type csv /tmp/canada_rtables.csv --headerline
    
    1. 我在这台主机上启动了mongo ..然后检查rtables.widgets集合中的记录数,它与导入的记录数相匹配。我们说50。

    2. 然后我通过运行类似的命令导入了美国的所有记录,如下所示:

    3.   

      mongoimport -h mongohost2 --port 27017 -d rtables -c widgets --type   csv /tmp/usa_rtables.csv --headerline

      1. 我检查了“primary”replicaset jjsr1中的记录,并且它在集合中有新记录。

      2. 其他两个数据集(jjrs0和jjrs2)上的其他两个数据库为空。事实上,两台服务器上的rtables数据库都是空的,如下所示:

      3.   

        jjrs2:PRIMARY>使用rtables       切换到db rtables       jlrs2:PRIMARY>显示数据库       管理员(空)       本地1.078GB       rtables(空)       jjrs2:PRIMARY>

        jjrs0:PRIMARY> show databases
        admin       (empty)
        local       1.078GB
        rtables  (empty)
        test        0.078GB
        jjrs0:PRIMARY> 
        

        问题

        1. 我是否正确假设数据将以一种方式划分,其中所有加拿大内容将在一个复制品中,美国数据在另一个复制品中?
        2. 如果是这样,我测试得当吗?
        3. 如果我的假设不正确,您能否根据我定义的分片键解释如何进行数据分割?
        4. 我发现以下帖子可能有关......但我无法将答案应用于我自己的问题..: Mongo sharding fails to split large collection between shards

          我还在考虑它。

          由于

          编辑1

          我在想,也许我应该使用标签作为分片键? 也许是这样的:

          mongos> sh.addShardTag("jjrs1", "CAN")
          mongos> sh.addShardTag("jjrs1", "USA")
          mongos> sh.addShardTag("jjrs0", "JPN")
          mongos> sh.addShardTag("jjrs2", "IND")
          mongos> sh.addShardTag("jjrs2", "TAI")
          mongos> sh.addShardTag("jjrs1", "VET")
          mongos> sh.status()
          

          接下来的问题是如何将位置字段中具有“可以”的每条记录与jjrs1相关联...

1 个答案:

答案 0 :(得分:0)

首先:

mongoimport -h mongohost2 ...

这是你的第一个错误。您将直接导入“常规” mongod 主机。您应该使用 mongos 进行导入,其中包含路由逻辑(哪些块位于哪个分片上)。

另外,请看一下以下内容:

chunks:
    jjrs1   1
{"location" : {"$minKey" : 1}, "name" : {"$minKey" : 1} } -->> 
{"location" : {"$maxKey" : 1}, "name" : {"$maxKey" : 1} } on : jjrs1 Timestamp(1, 0)

这可以理解为“对于每个位置和名称值,文档应该路由到jjrs1。

这也就不足为奇了。块是一系列具有特定范围内的分片键的文档。此外,每个块的默认大小为64MB。例如,如果文档的平均大小为64KB,那么在将块拆分为2之前,您必须插入1000多个文档(比如美国500+和加拿大500+)。

然后,sh.status()可能类似于:

 chunks:
    jjrs0   0
{"location" : {"$minKey" : 1}, "name" : {"$minKey" : 1} } -->> 
{"location" : "canada", "name" : {"$maxKey" : 1} } on : jjrs0 Timestamp(1, 0)
    jjrs1   1
{"location" : {"usa" : 1}, "name" : {"$minKey" : 1} } -->> 
{"location" : {"$maxKey" : 1}, "name" : {"$maxKey" : 1} } on : jjrs1 Timestamp(1, 0)
  

我在想,也许我应该使用标签作为分片键?也许是这样的:

这不是分片键,而是将标签与分片关联的机制。这是朝着正确方向迈出的一步,但还不够。

例如,使用上面的(虚构的)sh.status(),一旦块分成两部分,“加拿大”块就已迁移到jjrs0。假设您要将“美国”文档发送到jjrs0,这可能不是理想的行为。

为什么会这样?因为你错过了declaring tag ranges。没有这些,分片标记只是静态集群元数据。

您还必须按如下方式配置标记范围:

sh.addTagRange( "rtables.widgets", 
   { country: "usa", name: MinKey }, { country: "usa", name: MaxKey }, "USA")
sh.addTagRange( "rtables.widgets", 
   { country: "canada", name: MinKey }, { country: "canada", name: MaxKey }, "CAN")

为了将美国文件放在jjrs0碎片上,加拿大加入jjrs1,请执行以下操作:

  1. (可选)从jjrs1中删除所有widget个文档。
  2. 在帖子的编辑部分中声明分片代码(为了便于测试,CANUSA已经足够了。)
  3. 按上述方式声明标记范围。
  4. 使用mongos进行导入。
  5. 评论,对于其他国家/地区 - 标签尚未声明 - 将尝试平衡群集,这意味着将随机路由/迁移块以平衡数量碎片之间的块。