首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >控制MongoDB中的集合分布

控制MongoDB中的集合分布

作者头像
Sepmer Fi
发布2018-01-10 11:16:09
1.9K0
发布2018-01-10 11:16:09

分片标记(Shard tagging)是MongoDB 2.2.0版中的一项新功能。通过对集合进行标记使其被强制写入到本地数据中心,也可以用来将某个集合固定到一个分片或一系列分片中。

注意:尝试分片标记功能,必须使用2.2.0-rc0或更高版本。

使用此功能,首先需要启动一个分片群集:

> sharding = new ShardingTest({shards:3,chunksize:1})

这个命令将启动3个分片,一个配置服务器和一个mongos。并将所有的服务器日志输出到标准输出,所以我建议把这个shell先放在一边,然后使用另一个shell进行以下操作。

启动一个新的shell并连接到mongos(默认为端口30999),并创建一些分片的集合和数据来进行操作:

> // 记住,使用不同的shell
> conn = new Mongo("localhost:30999")
> db = conn.getDB("villains")
>
> // 启用分片
> sh.enableSharding("villains")
>
> // 将集合加入分片
> sh.shardCollection("villains.joker", {jokes:1});
> sh.shardCollection("villains.two-face", {luck:1});
> sh.shardCollection("villains.poison ivy", {flora:1});
> 
> // 添加数据
> for (var i=0; i<100000; i++) { db.joker.insert({jokes: Math.random(), count: i, time: new Date()}); }
> for (var i=0; i<100000; i++) { db["two-face"].insert({luck: Math.random(), count: i, time: new Date()}); }
> for (var i=0; i<100000; i++) { db["poison ivy"].insert({flora: Math.random(), count: i, time: new Date()}); }

现在我们有三个分片和三个集合。如果你查看一下主要的数据块在哪里,你应该看到数据在分片之间相当均衡:

> use config
> db.chunks.find({ns:“villains.joker”},{shard:1,_id:0})。sort({shard:1})
{“shard”:“shard0000”}
{“shard”:“shard0000”}
{“shard”:“shard0000”}
{“shard”:“shard0001”}
{“shard”:“shard0001”}
{“shard”:“shard0001”}
{“shard”:“shard0002”}
{“shard”:“shard0002”}
{“shard”:“shard0002”}
> db.chunks.find({ns:“villains.two-face”},{shard:1,_id:0})。sort({shard:1})
{“shard”:“shard0000”}
{“shard”:“shard0000”}
{“shard”:“shard0000”}
{“shard”:“shard0001”}
{“shard”:“shard0001”}
{“shard”:“shard0001”}
{“shard”:“shard0002”}
{“shard”:“shard0002”}
{“shard”:“shard0002”}
> db.chunks.find({ns:“villains.poison ivy”},{shard:1,_id:0})。sort({shard:1})
{“shard”:“shard0000”}
{“shard”:“shard0000”}
{“shard”:“shard0001”}
{“shard”:“shard0001”}
{“shard”:“shard0002”}
{“shard”:“shard0002”}
 
或许哈雷会说:“布丁”
或许哈雷会说:“布丁”

然而,我们的每个villains可不想和其他人混到一起,所以我们要分开储存这些集合:每个villain一个分片。我们的目标如下:

分片

命名空间

shard0000

“villains.joker”

shard0001

“villains.two-face”

shard0002

“villains.poison ivy”

要做到这一点,我们将使用标记标记描述了一个分片的属性,可以是任何属性(标签非常灵活)。所以,你可以把一个分片标记为“快”,“慢”,“东海岸”,“机架空间”或者随便什么东西。

在这个例子中,我们要标记一个碎片属于某个villain,所以我们将villain的昵称作为标签。

> sh.addShardTag(“shard0000”,“mr.j”)
> sh.addShardTag(“shard0001”,“harv”)
> sh.addShardTag(“shard0002”,“ivy”)

这就是说,“把任何标记为 ‘mr. j’的数据块放在shard0000分片上。“

我们要做的第二件事就是制定一个规则:“对于在villains.joker系列中创建的所有数据块,给他们标记‘mr. j’。“要做到这一点,我们可以使用addTagRange

> sh.addTagRange("villains.joker", {jokes:MinKey}, {jokes:MaxKey}, "mr. j")
> sh.addTagRange("villains.two-face", {luck:MinKey}, {luck:MaxKey}, "harv")
> sh.addTagRange("villains.poison ivy", {flora:MinKey}, {flora:MaxKey}, "ivy")
 

这条命令的作用是用 ‘mr. j’来标记villains.joker中的每一个数据块。(MinKey是负无穷大,MaxKey是正无穷大,因此所有的块落在这个范围内)。

现在让我们为其他两个集合做同样的事情:


> sh.addTagRange("villains.two-face", {luck:MinKey}, {luck:MaxKey}, "harv")
> sh.addTagRange("villains.poison ivy", {flora:MinKey}, {flora:MaxKey}, "ivy")

操作之后需要等几分钟(数据块的平衡需要一点时间),然后再来看这些集合当中的数据块。

> use config
> db.chunks.find({ns: "villains.joker"}, {shard:1, _id:0}).sort({shard:1})
{ "shard" : "shard0000" }
{ "shard" : "shard0000" }
{ "shard" : "shard0000" }
{ "shard" : "shard0000" }
{ "shard" : "shard0000" }
{ "shard" : "shard0000" }
{ "shard" : "shard0000" }
{ "shard" : "shard0000" }
{ "shard" : "shard0000" }
{ "shard" : "shard0000" }
> db.chunks.find({ns: "villains.two-face"}, {shard:1, _id:0}).sort({shard:1})
{ "shard" : "shard0001" }
{ "shard" : "shard0001" }
{ "shard" : "shard0001" }
{ "shard" : "shard0001" }
{ "shard" : "shard0001" }
{ "shard" : "shard0001" }
{ "shard" : "shard0001" }
{ "shard" : "shard0001" }
{ "shard" : "shard0001" }
{ "shard" : "shard0001" }
> db.chunks.find({ns: "villains.poison ivy"}, {shard:1, _id:0}).sort({shard:1})
{ "shard" : "shard0002" }
{ "shard" : "shard0002" }
{ "shard" : "shard0002" }
{ "shard" : "shard0002" }
{ "shard" : "shard0002" }
{ "shard" : "shard0002" }
{ "shard" : "shard0002" }
{ "shard" : "shard0002" }

使用标记进行伸缩

假设Two-Face对这种安排并不满意,并立即要求两台服务器提供数据(即要求拥有两个分片)。我们可以通过操纵标签将Joker 和Poison Ivy的集合移动到同一个分片,并将Harvey的集合扩展到两个分片:

> // move Poison Ivy to shard0000
> sh.addShardTag("shard0000", "ivy")
> sh.removeShardTag("shard0002", "ivy")
>
> // expand Two-Face to shard0002
> sh.addShardTag("shard0002", "harv")

现在,如果您等待几分钟并查看数据块,将看到Two-Face的集合分布在2个分片上,另外两个集合分布在shard0000分片上。


> db.chunks.find({ns: "villains.poison ivy"}, {shard:1, _id:0}).sort({shard:1})
{ "shard" : "shard0000" }
{ "shard" : "shard0000" }
{ "shard" : "shard0000" }
{ "shard" : "shard0000" }
{ "shard" : "shard0000" }
{ "shard" : "shard0000" }
{ "shard" : "shard0000" }
{ "shard" : "shard0000" }
{ "shard" : "shard0000" }
> db.chunks.find({ns: "villains.two-face"}, {shard:1, _id:0}).sort({shard:1})
{ "shard" : "shard0001" }
{ "shard" : "shard0001" }
{ "shard" : "shard0001" }
{ "shard" : "shard0001" }
{ "shard" : "shard0001" }
{ "shard" : "shard0002" }
{ "shard" : "shard0002" }
{ "shard" : "shard0002" }
{ "shard" : "shard0002" }
{ "shard" : "shard0002" }

“Bad heads, you get EBS.”
“Bad heads, you get EBS.”

然而,对于 Harvey来说,这仍然不太合适,他希望一块分片性能好,另一块分片性能差些。比方说,我们利用亚马逊的新服务,用SSD代替shard0002分片。然后我们划分流量:将 Harvey的50%的写入发送到SSD分片,50%发送到HDD分片。首先,我们将标签添加到分片,并为它们添加描述:

> sh.addShardTag("shard0001", "spinning")
> sh.addShardTag("shard0002", "ssd")

设定一个“运气”字段,运气值在0和1之间,我们设定如果运气<0.5,发送到HDD。如果运气> = 0.5,发送到SSD。

> sh.addTagRange("villains.two-face", {luck:MinKey}, {luck:.5}, "spinning")
> sh.addTagRange("villains.two-face", {luck:.5}, {luck:MaxKey}, "ssd")
 

现在,“倒霉”文档将被写入慢速磁盘,“好运”文档将写入SSD。

通过这种方式添加新的服务器,我们可以控制他们的负载情况。标记为DBA提供了对集合存放位置的控制权。

最后,我写了一个小脚本,为集合添加一个“home”方法,将它们固定在一个标签上。用法示例:


> // load the script
> load("batman.js")
> // put foo on bar
> db.foo.home("bar")
> // put baz on bar
> db.baz.home("bar")
> // move foo to bat
> db.foo.home("bat")
评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 使用标记进行伸缩
相关产品与服务
云数据库 MongoDB
腾讯云数据库 MongoDB(TencentDB for MongoDB)是腾讯云基于全球广受欢迎的 MongoDB 打造的高性能 NoSQL 数据库,100%完全兼容 MongoDB 协议,支持跨文档事务,提供稳定丰富的监控管理,弹性可扩展、自动容灾,适用于文档型数据库场景,您无需自建灾备体系及控制管理系统。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档