按应用或客户分段数据
在分片集群中,您可以创建区域来存储基于分片键的数据。您可以将每个区域与集群中的一个或多个分片相关联。一个分片可以与任何数量的区域相关联。在平衡的集群中,MongoDB 只将区域覆盖的数据块迁移到与该区域关联的分片。
提示
在分片一个空集合或不存在集合之前定义区域和区域范围,分片集合操作将为定义的区域范围创建数据块,以及覆盖分片键值范围的任何额外数据块,并根据区域范围执行初始数据块分配。这种初始创建和分配数据块允许更快地设置区域分片。初始分配后,平衡器将管理未来的数据块分配。
有关示例,请参阅为空或不存在的集合预定义区域和区域范围。
本教程向您展示了如何使用区域对数据进行分片。
考虑以下场景,在这些场景中,按应用或客户分片数据可能是必要的:
为多个应用提供服务的数据库
为多个客户提供服务的数据库
需要隔离应用或客户数据范围或子集的数据库
需要为应用或客户数据的范围或子集分配资源的数据库
此图说明了使用区域根据应用或客户分片数据的分片集群。这允许数据隔离到特定的分片。此外,每个分片都可以分配特定的硬件来满足存储在该分片上的数据性能需求。
场景
一个应用程序跟踪用户的分数以及一个client
字段,将分数存储在gamify
数据库下的users
集合中。每个可能的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
字段允许为每个不同的client
值创建一个区域。
userid
字段相对于country
提供了高基数和低频率分片键组件。
有关选择分片键的更多一般说明,请参阅选择分片键。
架构
该应用需要将分片添加到与特定客户端
关联的区域。
当前分片集群部署由四个分片组成。
区域
对于此应用,有两个客户端区域。
- 机器人客户端("robot")
- 此区域代表所有
client : robot
的文档。 - FruitOS客户端("fruitos")
- 此区域代表所有
client : fruitos
的文档。
写操作
使用区域,如果插入或更新的文档与配置的区域匹配,则只能将其写入该区域内的分片。
MongoDB可以将不匹配配置区域的文档写入集群中的任何分片。
注意
上述行为要求集群处于稳定状态,且没有违反配置区域的块。有关更多信息,请参阅均衡器的下一节。
读取操作
如果查询包含至少 client
字段,MongoDB 可以将查询路由到特定的分片。
例如,MongoDB 可以尝试对以下查询执行 目标读取操作
chatDB = db.getSiblingDB("gamify") chatDB.users.find( { "client" : "robot" , "userid" : "123" } )
没有 client
字段的查询执行 广播操作
均衡器
均衡器 将数据块迁移到适当的分片,同时尊重任何配置的区域。在迁移之前,分片可能包含违反配置区域的块。一旦均衡完成,分片应仅包含不违反其分配区域的范围的数据块。
添加或删除区域或区域范围可能会导致数据块迁移。根据数据集的大小以及区域或区域范围影响的块的数量,这些迁移可能会影响集群的性能。考虑在特定的计划时间运行您的 均衡器。有关如何设置调度窗口的教程,请参阅 调度均衡窗口
安全
对于运行 基于角色的访问控制 的分片集群,请以具有至少 clusterManager
角色的 admin
数据库用户进行身份验证。
过程
您必须连接到与目标 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()
查看已配置的分区。
为每个区域定义范围
使用 sh.addTagRange()
方法为 robot
客户端定义范围并将其关联到 robot
区域。
此方法需要
目标集合的完整命名空间
范围的包含下限
范围的排他上限
区域名称
sh.addTagRange( "gamify.users", { "client" : "robot", "userid" : MinKey }, { "client" : "robot", "userid" : MaxKey }, "robot" )
使用 sh.addTagRange()
方法为 fruitos
客户端定义范围并将其关联到 fruitos
区域。
此方法需要
目标集合的完整命名空间
范围的包含下限
范围的排他上限
区域名称
sh.addTagRange( "gamify.users", { "client" : "fruitos", "userid" : MinKey }, { "client" : "fruitos", "userid" : MaxKey }, "fruitos" )
《MinKey》和《MaxKey》值是用于比较的保留特殊值。《MinKey》始终比较为比其他任何可能的值都小,而《MaxKey》始终比较为比其他任何可能的值都大。配置的范围内捕获了每个客户端的用户。
启用均衡器
重新启用均衡器以重新平衡集群。
使用 sh.enableBalancing()
,指定集合的命名空间,以启动均衡器。
sh.enableBalancing("chat.message")
使用 sh.isBalancerRunning()
检查均衡器进程是否当前正在运行。
审查更改
下一次均衡器运行时,它将尊重配置的区域迁移跨分片的数据。
平衡完成后,仅包含具有 client : robot
的文档的 robot
区域分片,而仅包含具有 client : fruitos
的文档的 fruitos
区域分片。
您可以通过运行 sh.status()
来确认数据块分布。