在分片的集群中,您可以根据分 分片键 创建分分片的数据的 区域 。您可以将每个区域与集群中的一个或多个分片相关联。 一个分分片可以与任意数量的区域关联。 在均衡集群中, MongoDB仅将区域覆盖的数据段迁移到与该区域关联的分片。
提示
通过对空集合或不存在的集合进行分片之前定义区域和区域范围,分片集合操作会为定义的区域范围创建数据块以及任何其他数据块,以覆盖分片键值的整个范围,并执行基于区域范围的初始数据块分配。数据块的初始创建和分布可以更快地设置区域分片。在初始分布之后,负载均衡器将管理未来的数据段分布。
有关示例,请参阅为空集合或不存在的集合预先定义区域和区域范围。
本教程向您展示如何使用区域分割数据。
考虑以下场景,可能需要按应用程序或客户对数据进行分段:
一个数据库为多个应用程序提供服务
为多个客户提供服务的数据库
需要隔离应用程序或客户数据的范围或子集的数据库
需要为应用程序或客户数据的范围或子集分配资源的数据库
此图说明了一个分片集群,该集群使用区域根据应用程序或客户对数据进行分段。 这样就可以将数据隔离到特定的分片。 此外,每个分片都可以分配特定的硬件,以满足该分片上存储的数据的性能要求。
Scenario
应用程序追踪用户的分数以及client gamifyusers字段,将分数存储在collection集合下的数据库中。client的每个可能值都需要自己的区域,以便进行数据分段。 它还允许管理员优化与client关联的每个分片的硬件,以提高性能和成本。
以下文档表示两个用户的部分视图:
{ "_id" : ObjectId("56f08c447fe58b2e96f595fa"), "client" : "robot", "userid" : 123, "high_score" : 181, ..., } { "_id" : ObjectId("56f08c447fe58b2e96f595fb"), "client" : "fruitos", "userid" : 456, "high_score" : 210, ..., }
片键
users 集合使用 { client : 1, userid : 1 } 复合索引作为分片键。
每个文档中的client字段允许为每个不同的客户端值创建一个区域。
userid 字段为分片键提供相对于 country 的高关联基数和低频分量。
有关选择分片键的更多一般说明,请参阅选择分片键。
架构
应用程序需要将分片添加到与特定client关联的区域。
分片集群部署当前由四个分片组成。
区域
此应用程序有两个客户端区域。
- 机器人客户端(“机器人”)
- 此区域表示满足
client : robot条件的所有文档。 - FruitOS 客户端(“Fruitos”)
- 此区域表示满足
client : fruitos条件的所有文档。
写入操作
对于区域,如果插入或更新的文档与配置的区域匹配,则只能将其写入该区域内的分片。
MongoDB 可以将与已配置区域不匹配的文档写入集群中的任何分片。
注意
上述行为要求集群处于稳定状态,没有任何数据段违反已配置的区域。 有关更多信息,请参阅以下有关负载均衡器的部分。
读取操作
如果查询至少包含 client 字段,MongoDB 可以将查询路由到特定分片。
例如,MongoDB 可以尝试对以下查询执行针对性的读取操作:
chatDB = db.getSiblingDB("gamify") chatDB.users.find( { "client" : "robot" , "userid" : "123" } )
不带 client 字段的查询执行广播操作。
平衡器
负载均衡器会根据任何已配置区域将数据段迁移到相应的分片。在迁移之前,分片可能包含违反已配置区域的数据段。平衡完成后,分片应仅包含其范围不违反分配区域的数据段。
添加或删除区域或区域范围可能会导致数据段迁移。根据数据集的大小以及区域或区域范围影响的数据段数量,这些迁移可能会影响集群性能。考虑在特定的计划窗口运行负载均衡器。有关如何设置计划窗口的教程,请参阅计划平衡窗口。
安全性
对于在自管理部署中使用基于角色的访问控制运行的分分片的集群,请以至少在admin数据库上具有clusterManager角色的用户身份进行身份验证。
步骤
mongos您必须连接到与目标 分片集群 关联的 才能继续。您无法通过直接连接到分片来创建区域或区域范围。
禁用负载均衡器
必须在整个分分片集群上禁用负载负载均衡器,以确保在配置新区域时不会发生迁移。
使用sh.stopBalancer() 停止集群的负载均衡器。
sh.stopBalancer()
使用 sh.isBalancerRunning() 检查负载均衡器进程是否正在运行。等待当前所有平衡轮次完成后再继续。
将每个分片添加到相应的区域
将shard0000添加到robot区域。
sh.addShardTag("shard0000", "robot")
将shard0001添加到robot区域。
sh.addShardTag("shard0001", "robot")
将shard0002添加到fruitos区域。
sh.addShardTag("shard0002", "fruitos")
将shard0003添加到fruitos区域。
sh.addShardTag("shard0003", "fruitos")
运行sh.status()以查看为分片集群配置的区域。
定义每个区域的范围
定义robot客户端的范围,并使用sh.addTagRange()方法将其与robot区域关联。
此方法需要:
目标collection的完整命名空间
范围的下限(含)
范围的独占上限
区域名称
sh.addTagRange( "gamify.users", { "client" : "robot", "userid" : MinKey }, { "client" : "robot", "userid" : MaxKey }, "robot" )
定义fruitos客户端的范围,并使用sh.addTagRange()方法将其与fruitos区域关联。
此方法需要:
目标collection的完整命名空间
范围的下限(含)
范围的独占上限
区域名称
sh.addTagRange( "gamify.users", { "client" : "fruitos", "userid" : MinKey }, { "client" : "fruitos", "userid" : MaxKey }, "fruitos" )
MinKey 和 MaxKey 特殊值保留用于比较。MinKey 总是比其他所有可能的值都低,而 MaxKey 总是比其他所有可能的值都高。配置的范围捕获每个 client 的每个用户。
启用负载均衡器
重新启用负载均衡器以重新平衡集群。
使用 sh.enableBalancing(),指定集合的命名空间,启动负载均衡器。
sh.enableBalancing("chat.message")
使用 sh.isBalancerRunning() 检查负载均衡器进程是否正在运行。
查看变更
均衡完成后, robot区域中的分片仅包含带有client : robot的文档,而fruitos区域中的分片仅包含带有client : fruitos的文档。
您可以通过运行sh.status()来确认数据块分布。