背景资料
我定义了以下分片群集:
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
问题
要么我误解了分片键是如何工作的,要么是我错误地设置了某些东西......或者我可能没有正确验证我的数据。无论如何,这里发生了什么:
mongoimport -h mongohost2 --port 27017 -d rtables -c widgets --type csv /tmp/canada_rtables.csv --headerline
我在这台主机上启动了mongo ..然后检查rtables.widgets集合中的记录数,它与导入的记录数相匹配。我们说50。
然后我通过运行类似的命令导入了美国的所有记录,如下所示:
mongoimport -h mongohost2 --port 27017 -d rtables -c widgets --type csv /tmp/usa_rtables.csv --headerline
我检查了“primary”replicaset jjsr1中的记录,并且它在集合中有新记录。
其他两个数据集(jjrs0和jjrs2)上的其他两个数据库为空。事实上,两台服务器上的rtables数据库都是空的,如下所示:
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>
问题
我发现以下帖子可能有关......但我无法将答案应用于我自己的问题..: 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相关联...
答案 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
,请执行以下操作:
widget
个文档。CAN
和USA
已经足够了。)mongos
进行导入。评论,对于其他国家/地区 - 标签尚未声明 - 将尝试平衡群集,这意味着将随机路由/迁移块以平衡数量碎片之间的块。