按位置细分数据
在本页面
在分片群集中,您可以基于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
MinKey
和MaxKey
值是保留的特殊值,用于比较
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"
)
MinKey
和MaxKey
值是保留的特殊值,用于比较。 MinKey
总是比其他所有可能的值都低,而MaxKey
总是比其他所有可能的值都低。配置的范围捕获每个device
的每个用户。
country : UK
和country : DE
都分配给EU
区域。这会将带有UK
或DE
作为country
值的任何文档关联到 EU 数据中心。
启用平衡器(可选)
如果在之前的步骤中禁用了平衡器,请在此过程完成后重新启用平衡器以重新平衡群集。
使用sh.enableBalancing()(指定集合的名称空间)来启动平衡器。
sh.enableBalancing("chat.message")
使用sh.isBalancerRunning()检查平衡器进程当前是否正在运行。
查看更改
下次运行balancer时,它会在必要时splits个块,并在分片上migrates个块会尊重已配置的区域。
平衡完成后,NA
区域中的分片应仅包含country : NA
的文档,而EU
区域中的分片应仅包含country : UK
或country : DE
的文档。
NA
,UK
或DE
以外的其他值为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"
)
MinKey
和MaxKey
值是保留的特殊值,用于比较。 MinKey
总是比其他所有可能的值都低,而MaxKey
总是比其他所有可能的值都低。这样可以确保两个范围捕获creation_date
的整个可能值空间。
启用平衡器(可选)
如果在之前的步骤中禁用了平衡器,请在此过程完成后重新启用平衡器以重新平衡群集。
使用sh.enableBalancing()(指定集合的名称空间)启动平衡器
sh.enableBalancing("chat.messages")
使用sh.isBalancerRunning()检查平衡器进程当前是否正在运行。
查看更改
下次运行balancer时,它会在必要时splits个块,并在分片上migrates个块会尊重已配置的区域。
平衡之前,EU
区域中的碎片仅包含country : DE
或country : UK
的文档。带有country : MX
的文档可以存储在分片群集中的任何分片上。
平衡之后,EU
区域中的碎片仅应包含country : DE
的文档,而UK
区域中的碎片应仅包含country : UK
的文档。此外,NA
区域中的分片应仅包含country : US
或country : MX
的文档。
NA
,MX
,UK
或DE
以外的其他值为country
的文档可以驻留在群集中的任何分片上。
您可以通过运行sh.status()来确认块分配。