按应用程序或客户细分数据
在分片的集群中,您可以根据分 分片键 创建分分片的数据的 区域 。您可以将每个区域与集群中的一个或多个分片相关联。 一个分分片可以与任意数量的区域关联。 在均衡集群中, MongoDB仅将区域覆盖的数据段迁移到与该区域关联的分片。
提示
通过对空集合或不存在的集合进行分片之前定义区域和区域范围,分片集合操作会为定义的区域范围创建数据块以及任何其他数据块,以覆盖分片键值的整个范围,并执行基于区域范围的初始数据块分配。数据块的初始创建和分布可以更快地设置区域分片。在初始分布之后,负载均衡器将管理未来的数据段分布。
有关示例,请参阅为空集合或不存在的集合预先定义区域和区域范围。
本教程向您展示如何使用区域分割数据。
考虑以下场景,可能需要按应用程序或客户对数据进行分段:
一个数据库为多个应用程序提供服务
为多个客户提供服务的数据库
需要隔离应用程序或客户数据的范围或子集的数据库
需要为应用程序或客户数据的范围或子集分配资源的数据库
此图说明了一个分片集群,该集群使用区域根据应用程序或客户对数据进行分段。 这样就可以将数据隔离到特定的分片。 此外,每个分片都可以分配特定的硬件,以满足该分片上存储的数据的性能要求。
Scenario
应用程序追踪用户的分数以及client
gamify
users
字段,将分数存储在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()
来确认数据块分布。