按应用或 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组成。

使用区域的数据分段 Schema

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(),以查看为分片群集配置的区域。

定义每个区域的范围

定义robotClient 端的范围,并使用sh.addTagRange()方法将其关联到robot区域。

此方法要求:

  • 目标集合的完整名称空间

  • 范围的下限

  • 范围的专有上限

  • 区域名称

sh.addTagRange(
  "gamify.users",
  { "client" : "robot", "userid" : MinKey },
  { "client" : "robot", "userid" : MaxKey },
  "robot"
)

定义fruitosClient 端的范围,并使用sh.addTagRange()方法将其关联到fruitos区域。

此方法要求:

  • 目标集合的完整名称空间

  • 范围的下限

  • 范围的专有上限

  • 区域名称

sh.addTagRange(
  "gamify.users",
  { "client" : "fruitos", "userid" : MinKey },
  { "client" : "fruitos", "userid" : MaxKey },
  "fruitos"
)

MinKeyMaxKey值是保留的特殊值,用于比较。 MinKey总是比其他所有可能的值都低,而MaxKey总是比其他所有可能的值都低。配置的范围捕获每个client的每个用户。

启用平衡器

重新启用平衡器以重新平衡集群。

使用sh.enableBalancing()(指定集合的名称空间)来启动平衡器。

sh.enableBalancing("chat.message")

使用sh.isBalancerRunning()检查平衡器进程当前是否正在运行。

查看更改

balancer下次运行时,它会跨分片splitsmigrates遵守已配置的区域。

平衡完成后,robot区域中的碎片仅包含client : robot的文档,而fruitos区域中的碎片仅包含client : fruitos的文档。

您可以通过运行sh.status()来确认块分配。