Mongo是否将标记识别的分片数据库中新更新的文档移动到正确的分片?
我们使用MongoDb ver进行以下设置。 2.4.6并使用C#驱动程序1.8.3,它没有返回标记感知分片的更新方案的预期结果。请协助查看以下情况,并告诉我们MongoDb是否具备此功能。
我们为实验设置了以下内容:
//use the default 'test' database
db = db.getSiblingDB('test');`
//Add shards
sh.addShard( "shard0001.local:27017" );
sh.addShard( "shard0002.local:27017" );
//Enable sharding for the database,
sh.enableSharding("test");
//Enable sharding for a collection,
sh.shardCollection("test.persons", { "countryCode": 1, "_id": 1 } );
//Add shard tags,
sh.addShardTag("shard0001", "USA");
sh.addShardTag("shard0002", "JPN");
//Tag shard key ranges,
sh.addTagRange("test.persons", { countryCode: 0 }, { countryCode: 1 }, "USA");
sh.addTagRange("test.persons", { countryCode: 1 }, { countryCode: 2 }, "JPN");
然后我们为初始数据填充执行以下脚本:
//MongoDB sharding test,
db = db.getSiblingDB('test')
//Load data
//USA: countryCode 0
//JPN: countryCode 1
for (var i=0; i < 1000, i++) {
db.persons.insert( { name: "USA-" + i, countryCode: 0 } )
db.persons.insert( { name: "JPN-" + i, countryCode: 1 } )
此时,每个分片有1000条记录,shard0001有1000条美国国家代码记录,shard0002有1000条JPN记录。
从C#开始,我们有以下伪代码:
collection.insert( 1 document of countryCode=0)
collection.insert( 1 document of countryCode=1)
执行后,我们为每个分片提供了1001个文档,到目前为止一直很好。
然后我们使用_id将shard0001中的一个文档从countryCode = 0更新为countryCode = 1。但是,我们最终在JPN shard(shard0002)中有1002条记录,在美国碎片(shard0001)中有1001条记录。似乎Mongos基于新的countryCode为1将更新路由到shard0002并执行了插入,并且从未在shard0001中对文档进行更新。因此,现在我们在两个不同的分片中有2个相同_id的文档。
我们期待mongo会更新shard0001中的实际文档,然后意识到将countryCode从0更改为1会将该文档移动到shard0002。 Mongo会自动执行此操作吗?
我们知道我们可以手动从shard0001中删除文档记录,我们是否真的必须自己手动删除?
答案 0 :(得分:0)
如果您检查了密钥范围对齐的documentation,则会发出通知:“要为一系列分片键分配标记,请在连接到mongos实例时使用sh.addTagRange()方法。任何给定的分片键范围可能只有一个指定的标记。您不能重叠定义的范围,或多次标记相同的范围。 “ 原因是在背景中mongodb将使分割具有仅与特定标签键范围相关的块,并且这样它们能够根据标记移动aroud。因此,标签定义的对齐有两个步骤:
我假设您检查了连接那里的分片一侧的文档数量,而不是直接通过mongos实例。这是由于误解了所描述的行为。天气这是一个bug还是没有你最终得到了两个文档,但由于分片键映射,您只能通过mongos访问其中一个由于基于键的范围对齐。如果它没有自动删除它肯定是一个BUG,它应该被解决。我无法从当前位置查看jira。我会设置一些测试并回复你的结果。
根据您使用save命令执行更新和documentation的注释,情况是您使用
保存文档{countrycode:0 _id:x}
组合是一个新组合(您之前有{countrycode:1 _id:x})_id与另一个文档(旧文档)相同,新文档驻留在另一个分片上(这是真的)由于标记是基于国家代码),因为仅在给定的分片和集合中确保_id字段的唯一性,所以它将被插入而没有问题。在不同的分片中,如果_id不是分片键,或者不是复合分片键中的第一个分片键,则_id字段的值没有保证是全局唯一的。基本上,因为它生成它很可能是唯一的,尽管这种情况,当你提出建议给予相同的_id预先形成更新类行为。
为您的问题提供答案:如果您的情况不符合预期,您必须删除旧文档而不是创建新文档,或者更安全地将旧文档标记为已删除(带有标记左右,并在应用程序端处理它,然后查找已删除的文档,并在需要时真正删除它们(如果空间不足)。