按位置细分数据
在分片的集群中,您可以根据分 分片键 创建分分片的数据的 区域 。您可以将每个区域与集群中的一个或多个分片相关联。 一个分分片可以与任意数量的区域关联。 在均衡集群中, MongoDB仅将区域覆盖的数据段迁移到与该区域关联的分片。
提示
通过对空集合或不存在的集合进行分片之前定义区域和区域范围,分片集合操作会为定义的区域范围创建数据块以及任何其他数据块,以覆盖分片键值的整个范围,并执行基于区域范围的初始数据块分配。数据块的初始创建和分布可以更快地设置区域分片。在初始分布之后,负载均衡器将管理未来的数据段分布。
有关示例,请参阅为空集合或不存在的集合预先定义区域和区域范围。
本教程使用分区,根据地理区域对数据进行分段。
以下是按地理区域分割数据的一些示例使用案例:
必须按国家对用户数据进行分段的应用程序
必须按国家/地区分配资源的数据库
下图展示了一个使用地理区域来管理和满足数据分段要求的分片集群。
Scenario
财务相关聊天应用程序记录消息,跟踪原始用户所在的国家/地区。 应用程序将日志存储在messages
集合下的chat
数据库中。聊天包含的信息必须按国家/地区分段,以便该国家/地区本地服务器为该国家/地区的用户提供读写请求。一组国家/地区可以分配相同的区域以共享资源。
该应用程序目前在美国、英国和德国拥有用户。country
字段根据 ISO3166 -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" ..., }
片键
messages
集合使用 { country : 1, userid : 1 }
复合索引作为分片键。
每个文档中的 country
字段允许为每个不同的国家/地区值创建一个区域。
userid
字段为分片键提供相对于 country
的高关联基数和低频分量。
有关选择分片键的更多一般说明,请参阅选择分片键。
架构
分片集群在两个数据中心拥有分片,一个数据中心位于欧洲,另一个位于北美。
区域
该应用程序需要为每个数据中心提供一个区域。
EU
- 欧洲数据中心在此数据中心部署的分片将分配到
EU
区域。对于使用
EU
数据中心进行本地读写的每个国家/地区,请使用以下命令为EU
区域创建区域范围:下限
{ "country" : <country>, "userid" : MinKey }
上限
{ "country" : <country>, "userid" : MaxKey }
NA
- 北美数据中心在此数据中心部署的分片将分配到
NA
区域。对于使用
NA
数据中心进行本地读写的每个国家/地区,请使用以下命令为NA
区域创建区域范围:下限
{ "country" : <country>, "userid" : MinKey }
上限
{ "country" : <country>, "userid" : MaxKey }
写入操作
对于区域,如果插入或更新的文档与配置的区域匹配,则只能将其写入该区域内的分片。
MongoDB 可以将与已配置区域不匹配的文档写入集群中的任何分片。
注意
上述行为要求集群处于稳定状态,没有任何数据块违反已配置的分区。有关更多信息,请参阅以下有关均衡器的部分。
读取操作
如果查询至少包含 country
字段,MongoDB 可以将查询路由到特定分片。
例如,MongoDB 可以尝试对以下查询执行针对性的读取操作:
chatDB = db.getSiblingDB("chat") chatDB.messages.find( { "country" : "UK" , "userid" : "123" } )
不带 country
字段的查询执行广播操作。
平衡器
负载均衡器会根据任何已配置区域将数据段迁移到相应的分片。在迁移之前,分片可能包含违反已配置区域的数据段。平衡完成后,分片应仅包含其范围不违反分配区域的数据段。
添加或删除区域或区域范围可能会导致数据段迁移。根据数据集的大小以及区域或区域范围影响的数据段数量,这些迁移可能会影响集群性能。考虑在特定的计划窗口运行负载均衡器。有关如何设置计划窗口的教程,请参阅计划平衡窗口。
安全性
对于在自管理部署中使用基于角色的访问控制运行的分分片的集群,请以至少在admin
数据库上具有clusterManager
角色的用户身份进行身份验证。
步骤
必须连接到 mongos
才能创建区域和区段范围。不能通过直接连接到分片来创建区域或区域范围。
禁用负载均衡器(可选)
为了减少性能影响,可以在整个分分片集群上禁用负载负载均衡器,以确保在配置新区域时不会发生迁移。
使用sh.stopBalancer()
停止集群的负载均衡器。
sh.stopBalancer()
使用 sh.isBalancerRunning()
检查负载均衡器进程是否正在运行。等待当前所有平衡轮次完成后再继续。
将每个分片添加到相应的区域
将北美数据中心中的每个分片添加到 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
值的文档关联到欧盟数据中心。
启用负载均衡器(可选)
如果在之前的步骤中停用了负载均衡器,请在完成此步骤后重新启用负载均衡器,以重新均衡集群。
使用 sh.enableBalancing()
,指定集合的命名空间,启动负载均衡器。
sh.enableBalancing("chat.message")
使用 sh.isBalancerRunning()
检查负载均衡器进程是否正在运行。
查看更改
下次负载均衡器运行时,它会在必要时分割数据段,并根据配置的区域在分片之间迁移数据段。
均衡完成后:
NA
区域中的分片应仅包含带有country : US
的文档,并且EU
区域中的分片应仅包含带有country : UK
或country : DE
的文档。
带有 country
值(除US
、 UK
或DE
之外)的文档可以驻留在集群的任何分片上。
要确认数据段的分布,请运行 sh.status()
。
更新区域
该应用程序需要以下更新:
带有
country : UK
的文档必须与新的UK
数据中心关联。必须迁移EU
数据中心中的所有数据聊天应用程序目前已对墨西哥用户提供支持。带有
country : MX
的文档必须路由到NA
数据中心。
执行以下步骤以更新区域范围。
禁用负载均衡器(可选)
为了减少性能影响,可以在整个分分片集群上禁用负载负载均衡器,以确保在配置新区域或删除旧区域时不会发生迁移。
使用sh.stopBalancer()
停止集群的负载均衡器。
sh.stopBalancer()
使用 sh.isBalancerRunning()
检查负载均衡器进程是否正在运行。等待当前所有平衡轮次完成后再继续。
添加新的UK
区域
将 UK
数据中心中的每个分片添加到 UK
分区。
sh.addShardTag("<shard name>", "UK")
可以通过运行 sh.status()
来查看分配给任何给定分片的区域。
删除旧区域范围
使用 sh.removeTagRange()
方法删除与 UK
国家关联的旧区域范围。此方法需要:
目标集合的完整命名空间。
范围的下限(包含在内)。
范围的独占上限。
sh.removeTagRange( "chat.messages", { "country" : "UK", "userid" : MinKey }, { "country" : "UK", "userid" : MaxKey } )
添加新的区域范围
对于 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
总是比其他所有可能的值都高。确保这两个范围涵盖了 userid
的整个可能值空间。
启用负载均衡器(可选)
如果在之前的步骤中停用了负载均衡器,请在完成此步骤后重新启用负载均衡器,以重新均衡集群。
使用 sh.enableBalancing()
,同时指定集合的命名空间,以启动负载均衡器
sh.enableBalancing("chat.messages")
使用 sh.isBalancerRunning()
检查负载均衡器进程是否正在运行。
查看变更
下次负载均衡器运行时,它会在必要时分割数据段,并根据配置的区域在分片之间迁移数据段。
均衡之前:
EU
区域中的分片仅包含country : DE
或country : UK
的文档,以及指定
country : MX
的文档可以存储在分片集群中的任何分片上。
平衡后:
EU
区域中的分片仅包含指定country : DE
的文档;在
UK
区域中的分片仅包含country : UK
文档,并且NA
区域中的分片仅包含指定country : US
或country : MX
的文档。
带有 country
值(除US
、 MX
、UK
或 DE
之外)的文档可以驻留在集群的任何分片上。
要确认数据段的分布,请运行 sh.status()
。