按应用或 Client 细分数据
在本页面
在分片群集中,您可以基于shard key创建zones的分片数据。您可以将每个区域与集群中的一个或多个分片关联。分片可以与任意数量的区域关联。在平衡群集中,MongoDB 仅将区域覆盖的chunks迁移到与该区域关联的分片。
本教程向您展示如何使用Zones细分数据。
考虑以下可能需要按应用程序或 Client 细分数据的方案:
-
服务多个应用程序的数据库
-
服务多个 Client 的数据库
-
需要隔离应用程序或 Client 数据的范围或子集的数据库
-
需要为应用程序或 Client 数据的范围或子集分配资源的数据库
该图说明了一个分片群集,该群集使用区域根据应用程序或 Client 对数据进行分段。这允许将数据隔离到特定的分片。此外,每个分片都可以分配特定的硬件,以适合存储在该分片上的数据的性能要求。
Scenario
应用程序跟踪用户的分数以及client
字段,并将分数存储在users
集合下的gamify
数据库中。 client
的每个可能值都需要其自己的区域以允许数据分段。它还允许 Management 员针对与client
关联的每个分片优化硬件,以提高性能和成本。
以下文档代表了两个用户的部分视图:
{
"_id" : ObjectId("56f08c447fe58b2e96f595fa"),
"client" : "robot",
"userid" : 123,
"high_score" : 181,
...,
}
{
"_id" : ObjectId("56f08c447fe58b2e96f595fb"),
"client" : "fruitos",
"userid" : 456,
"high_score" : 210,
...,
}
Shard Key
users
集合使用{ client : 1, userid : 1 }
复合索引作为分片键。
每个文档中的client
字段允许为每个不同的 Client 值创建区域。
userid
字段相对于country
为分片键提供高cardinality和低frequency的分量。
Architecture
该应用程序需要将分片添加到与特定client
关联的区域中。
分片群集部署当前由四个shards组成。
Zones
对于此应用程序,有两个 Client 端区域。
-
机器人 Client 端(“机器人”)
- 此区域代表
client : robot
的所有文档。
- 此区域代表
-
FruitOSClient 端(“ fruitos”)
- 此区域代表
client : fruitos
的所有文档。
- 此区域代表
Write Operations
对于区域,如果插入或更新的文档与配置的区域匹配,则只能将其写入该区域内的分片。
MongoDB 可以将与配置的区域不匹配的文档写入集群中的任何分片。
Note
上述行为要求群集处于稳定状态,且没有块违反配置的区域。有关更多信息,请参见balancer的以下部分。
Read Operations
如果查询至少包含client
字段,则 MongoDB 可以将查询路由到特定的分片。
例如,MongoDB 可以对以下查询尝试有针对性的读取操作:
chatDB = db.getSiblingDB("gamify")
chatDB.users.find( { "client" : "robot" , "userid" : "123" } )
没有client
字段的查询执行broadcast operations。
Balancer
balancer migrates块分配到适当的分片,尊重任何已配置的区域。在迁移之前,碎片可能包含违反已配置区域的块。平衡完成后,分片应仅包含范围不违反其指定区域的块。
添加或删除区域或区域范围可能导致块迁移。根据数据集的大小以及区域或区域范围影响的块数,这些迁移可能会影响群集性能。考虑在特定的 sched 时段内运行balancer。有关如何设置计划窗口的教程,请参见安排平衡窗口。
Security
对于以基于角色的访问控制运行的分片群集,请以admin
数据库上至少具有clusterManager角色的用户身份进行身份验证。
Procedure
您必须连接到与目标sharded cluster关联的mongos才能 continue。您不能通过直接连接到shard来创建区域或区域范围。
禁用平衡器
必须在集合上禁用平衡器,以确保在配置新区域时不进行任何迁移。
使用sh.disableBalancing()(指定集合的名称空间)来停止平衡器。
sh.disableBalancing("chat.message")
使用sh.isBalancerRunning()检查平衡器进程当前是否正在运行。等到当前的所有平衡操作完成后再 continue。
将每个分片添加到适当的区域
将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
Client 端的范围,并使用sh.addTagRange()方法将其关联到robot
区域。
此方法要求:
-
目标集合的完整名称空间
-
范围的下限
-
范围的专有上限
-
区域名称
sh.addTagRange(
"gamify.users",
{ "client" : "robot", "userid" : MinKey },
{ "client" : "robot", "userid" : MaxKey },
"robot"
)
定义fruitos
Client 端的范围,并使用sh.addTagRange()方法将其关联到fruitos
区域。
此方法要求:
-
目标集合的完整名称空间
-
范围的下限
-
范围的专有上限
-
区域名称
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()检查平衡器进程当前是否正在运行。
查看更改
balancer下次运行时,它会跨分片splits和migrates遵守已配置的区域。
平衡完成后,robot
区域中的碎片仅包含client : robot
的文档,而fruitos
区域中的碎片仅包含client : fruitos
的文档。
您可以通过运行sh.status()来确认块分配。