按位置细分数据

在本页面

在分片群集中,您可以基于shard key创建zones的分片数据。您可以将每个区域与集群中的一个或多个分片关联。分片可以与任意数量的区域关联。在平衡群集中,MongoDB 仅将区域覆盖的chunks迁移到与该区域关联的分片。

本教程使用Zones根据地理区域对数据进行细分。

以下是一些按地理区域细分数据的示例用例:

  • 需要根据地理国家/地区细分用户数据的应用程序

  • 需要根据地理国家分配资源的数据库

下图说明了分片群集,该分片群集使用基于地理的区域来 Management 和满足数据分段要求。

基于区域的图地理分布

Scenario

金融聊天应用程序记录消息,跟踪原始用户的国家。该应用程序将日志存储在messages集合下的chat数据库中。聊天包含必须按国家/地区细分的信息,以使该国家/地区的本地服务器为该国家/地区的用户提供读写请求。可以将一组国家/地区分配给同一区域,以便共享资源。

该应用程序当前在美国,英国和德国拥有用户。 country字段基于用户的ISO 3166-1 Alpha-2两个字符的国家/地区代码表示用户所在的国家/地区。

以下文档代表三个聊天消息的部分视图:

{
  "_id" : ObjectId("56f08c447fe58b2e96f595fa"),
  "country" : "US",
  "userid" : 123,
  "message" : "Hello there",
  ...,
}
{
  "_id" : ObjectId("56f08c447fe58b2e96f595fb"),
  "country" : "UK",
  "userid" : 456,
  "message" : "Good Morning"
  ...,
}
{
  "_id" : ObjectId("56f08c447fe58b2e96f595fc"),
  "country" : "DE",
  "userid" : 789,
  "message" : "Guten Tag"
  ...,
}

Shard Key

messages集合使用{ country : 1, userid : 1 }复合索引作为分片键。

每个文档中的country字段允许为每个不同的国家/地区值创建区域。

userid字段相对于country为分片键提供高cardinality和低frequency的分量。

有关选择分片键的更多常规说明,请参见选择分片键

Architecture

分片群集在两个数据中心中有分片-一个在欧洲,另一个在北美。

用于支持地理分布架构的区域图

Zones

此应用程序每个数据中心需要一个区域。

  • EU-欧洲数据中心

    • 部署在此数据中心上的碎片已分配到EU区域。

对于每个使用EU数据中心进行本地读写的国家/地区,请为EU区域创建一个区域范围,其中包括:

  • 下限{ "country" : <country>, "userid" : MinKey }

  • 上限{ "country" : <country>, "userid" : MaxKey }

  • NA-北美数据中心

    • 部署在此数据中心上的碎片已分配到NA区域。

对于每个使用NA数据中心进行本地读写的国家/地区,请为NA区域创建一个区域范围,其中包括:

  • 下限{ "country" : <country>, "userid" : MinKey }

  • 上限{ "country" : <country>, "userid" : MaxKey }

Note

MinKeyMaxKey值是保留的特殊值,用于比较

Write Operations

对于区域,如果插入或更新的文档与配置的区域匹配,则只能将其写入该区域内的分片。

MongoDB 可以将与配置的区域不匹配的文档写入集群中的任何分片。

Note

上述行为要求群集处于稳定状态,且没有块违反配置的区域。有关更多信息,请参见balancer的以下部分。

Read Operations

如果查询至少包含country字段,则 MongoDB 可以将查询路由到特定的分片。

例如,MongoDB 可以对以下查询尝试有针对性的读取操作

chatDB = db.getSiblingDB("chat")
chatDB.messages.find( { "country" : "UK" , "userid" : "123" } )

没有country字段的查询执行broadcast operations

Balancer

balancer migrates块分配到适当的分片,尊重任何已配置的区域。在迁移之前,碎片可能包含违反已配置区域的块。平衡完成后,分片应仅包含范围不违反其指定区域的块。

添加或删除区域或区域范围可能导致块迁移。根据数据集的大小以及区域或区域范围影响的块数,这些迁移可能会影响群集性能。考虑在特定的 sched 时段内运行balancer。有关如何设置计划窗口的教程,请参见安排平衡窗口

Security

对于以基于角色的访问控制运行的分片群集,请以admin数据库上至少具有clusterManager角色的用户身份进行身份验证。

Procedure

您必须连接到mongos才能创建区域和区域范围。您不能通过直接连接到shard来创建区域或区域范围。

禁用平衡器(可选)

为了减少对性能的影响,可以在集合上禁用平衡器,以确保在配置新区域时不进行任何迁移。

使用sh.disableBalancing()(指定集合的名称空间)来停止平衡器。

sh.disableBalancing("chat.message")

使用sh.isBalancerRunning()检查平衡器进程当前是否正在运行。等到当前的所有平衡操作完成后再 continue。

将每个分片添加到适当的区域

将北美数据中心中的每个分片添加到NA区域。

sh.addShardTag(<shard name>, "NA")

将欧洲数据中心中的每个分片添加到EU区域。

sh.addShardTag(<shard name>, "EU")

您可以通过运行sh.status()查看分配给任何给定分片的区域。

定义每个区域的范围

对于其中country : US的分片键值,定义一个分片键范围,并使用sh.addTagRange()方法将其与NA区域关联。此方法要求:

  • 目标集合的完整名称空间。

  • 范围的下限值。

  • 范围的唯一上限。

  • 区域名称。

sh.addTagRange(
  "chat.messages",
  { "country" : "US", "userid" : MinKey },
  { "country" : "US", "userid" : MaxKey },
  "NA"
)

对于其中country : UK的分片键值,定义一个分片键范围,并使用sh.addTagRange()方法将其与EU区域关联。此方法要求:

  • 目标集合的完整名称空间。

  • 范围的下限值。

  • 范围的唯一上限。

  • 区域名称。

sh.addTagRange(
  "chat.messages",
  { "country" : "UK", "userid" : MinKey },
  { "country" : "UK", "userid" : MaxKey },
  "EU"
)

对于其中country : DE的分片键值,定义一个分片键范围,并使用sh.addTagRange()方法将其与EU区域关联。此方法要求:

  • 目标集合的完整名称空间。

  • 范围的下限值。

  • 范围的唯一上限。

  • 区域名称。

sh.addTagRange(
  "chat.messages",
  { "country" : "DE", "userid" : MinKey },
  { "country" : "DE", "userid" : MaxKey },
  "EU"
)

MinKeyMaxKey值是保留的特殊值,用于比较。 MinKey总是比其他所有可能的值都低,而MaxKey总是比其他所有可能的值都低。配置的范围捕获每个device的每个用户。

country : UKcountry : DE都分配给EU区域。这会将带有UKDE作为country值的任何文档关联到 EU 数据中心。

启用平衡器(可选)

如果在之前的步骤中禁用了平衡器,请在此过程完成后重新启用平衡器以重新平衡群集。

使用sh.enableBalancing()(指定集合的名称空间)来启动平衡器。

sh.enableBalancing("chat.message")

使用sh.isBalancerRunning()检查平衡器进程当前是否正在运行。

查看更改

下次运行balancer时,它会在必要时splits个块,并在分片上migrates个块会尊重已配置的区域。

平衡完成后,NA区域中的分片应仅包含country : NA的文档,而EU区域中的分片应仅包含country : UKcountry : DE的文档。

NAUKDE以外的其他值为country的文档可以驻留在群集中的任何分片上。

您可以通过运行sh.status()来确认块分配。

Updating Zones

该应用程序需要以下更新:

  • 现在必须将具有country : UK的文档关联到新的UK数据中心。 EU数据中心中的任何数据都必须迁移

  • 聊天应用程序现在支持墨西哥的用户。带有country : MX的文档必须路由到NA数据中心。

执行以下过程以更新区域范围。

禁用平衡器(可选)

为了减少对性能的影响,可以在集合上禁用平衡器,以确保在配置新区域或删除旧区域时不进行任何迁移。

使用sh.disableBalancing()(指定集合的名称空间)来停止平衡器

sh.disableBalancing("chat.messages")

使用sh.isBalancerRunning()检查平衡器进程当前是否正在运行。等到当前的所有平衡操作完成后再 continue。

添加新的英国区域

UK数据中心中的每个分片添加到UK区域。

sh.addShardTag("<shard name>", "UK")

您可以通过运行sh.status()查看分配给任何给定分片的区域。

删除旧的区域范围

使用sh.removeTagRange()方法删除与UK国家相关的旧区域范围。此方法要求:

  • 目标集合的完整名称空间。

  • 范围的下限值。

  • 范围的唯一上限。

  • 区域名称。

sh.removeTagRange(
  "chat.messages",
  { "country" : "UK", "userid" : MinKey },
  { "country" : "UK", "userid" : MaxKey }
  "EU"
)

添加新的区域范围

对于其中country : UK的分片键值,定义一个分片键范围,并使用sh.addTagRange()方法将其与UK区域关联。此方法要求:

  • 目标集合的完整名称空间。

  • 范围的下限值。

  • 范围的唯一上限。

  • 区域名称。

sh.addTagRange(
  "chat.message",
  { "country" : "UK", "userid" : MinKey },
  { "country" : "UK", "userid" : MaxKey },
  "UK"
)

对于其中country : MX的分片键值,定义一个分片键范围,并使用sh.addTagRange()方法将其与NA区域关联。此方法要求:

  • 目标集合的完整名称空间。

  • 范围的下限值。

  • 范围的唯一上限。

  • 区域名称。

sh.addTagRange(
  "chat.messages",
  { "country" : "MX", "userid" : MinKey },
  { "country" : "MX", "userid" : MaxKey },
  "NA"
)

MinKeyMaxKey值是保留的特殊值,用于比较。 MinKey总是比其他所有可能的值都低,而MaxKey总是比其他所有可能的值都低。这样可以确保两个范围捕获creation_date的整个可能值空间。

启用平衡器(可选)

如果在之前的步骤中禁用了平衡器,请在此过程完成后重新启用平衡器以重新平衡群集。

使用sh.enableBalancing()(指定集合的名称空间)启动平衡器

sh.enableBalancing("chat.messages")

使用sh.isBalancerRunning()检查平衡器进程当前是否正在运行。

查看更改

下次运行balancer时,它会在必要时splits个块,并在分片上migrates个块会尊重已配置的区域。

平衡之前,EU区域中的碎片仅包含country : DEcountry : UK的文档。带有country : MX的文档可以存储在分片群集中的任何分片上。

平衡之后,EU区域中的碎片仅应包含country : DE的文档,而UK区域中的碎片应仅包含country : UK的文档。此外,NA区域中的分片应仅包含country : UScountry : MX的文档。

NAMXUKDE以外的其他值为country的文档可以驻留在群集中的任何分片上。

您可以通过运行sh.status()来确认块分配。