1

Mongo 是否将标签感知分片数据库中新更新的文档移动到正确的分片?

我们使用 MongoDb 版本进行了以下设置。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 条日本国家代码记录。

在 C# 中,我们有以下伪代码:

collection.insert( 1 document of countryCode=0)
collection.insert( 1 document of countryCode=1)

执行后,每个分片都有 1001 个文档,到目前为止一切正常。

然后我们将 shard0001 中的一个文档从 countryCode=0 更新为 countryCode=1 并使用 _id。然而,我们最终在 JPN 分片(shard0002)中有 1002 条记录,在美国分片(shard0001)中有 1001 条记录。Mongos 似乎根据新的 countryCode 1 将更新路由到 shard0002 并执行了插入,并且从未对 shard0001 中的文档进行更新。因此,现在我们在两个不同的分片中有 2 个具有相同 _id 的文档。

我们原以为 mongo 会更新 shard0001 中的实际文档,然后意识到将 countryCode 从 0 更改为 1 会将该文档移动到 shard0002 中。Mongo 会自动执行此操作吗?

我们知道我们可以手动从 shard0001 中删除文档记录,我们真的必须自己手动执行此操作吗?

4

1 回答 1

0

如果您检查 keyrange 分配的文档,它会注意到:“要将标签分配给一系列分片键,请在连接到 mongos 实例时使用 sh.addTagRange() 方法。任何给定的分片键范围可能只分配一个标记。您不能重叠定义的范围,或多次标记同一范围。” 原因是在背景中,mongodb 将拆分为具有仅与该特定标记键范围相关的块,这样他们就可以根据标记。因此,标签定义的对齐通过两个步骤来确保:

  • 引擎进行拆分以生成具有专用于一个分片标签的键范围的块
  • 平衡轮中的块将根据当前的分片标签映射对齐/移动。

我假设您从直接连接那里的分片一侧检查了文档的数量,而不是通过 mongos 实例。 不管您是否最终使用了这两个文档,这都是一个错误,但是由于分片键映射,由于基于键范围的对齐方式,您只能通过 mongos 访问其中一个。如果它没有自动删除,那肯定是一个BUG,应该解决。我无法从当前位置检查 jira。我将设置一些测试,然后将结果与您联系。这是由于对所描述行为的误解。

根据您使用 save 命令执行更新和此文档的评论,情况是您使用以下命令保存文档时

{国家代码:0 _id:x}

组合是一个新的(你以前有一个 {countrycode:1 _id:x}),_id 与另一个文档(旧的)相同,并且新文档驻留在另一个分片上(这是真的,因为标记基于国家/地区代码),由于 _id 字段的唯一性仅在给定的分片和集合内确保,它将毫无问题地插入。在不同的分片中,如果 _id 不是分片键,或者不是复合分片键中的第一个,则不保证 _id 字段的值是全局唯一的。基本上,当它生成时,它很可能是独一无二的,尽管在这种情况下,当您提议时提供相同的 _id 来执行更新类型的行为。

回答您的问题:如果您的这种情况不是预期的,您必须删除旧文档而不是创建新文档,或者更安全地将旧文档标记为已删除(使用标志左右,并处理它在应用程序端),然后查找已删除的文档并在需要时真正删除它们(如果空间不足)。

于 2013-10-15T09:31:27.460 回答