专栏首页控制MongoDB中的集合分布

控制MongoDB中的集合分布

分片标记(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.”

然而,对于 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")

本文的版权归 Sepmer Fi 所有,如需转载请联系作者。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 分片:以太坊可扩展性问题的解决方案?

    以太坊区块链的创新本质毋庸置疑,其智能合约功能促进了去中心化应用程序(DApps)和初首次币发行(ICOs)的发展。然而,尽管迄今为止以太坊取得了立竿见影的成功...

    Sepmer Fi
  • 编程之书系列:如何选择一本合适的编程书

    [本文由John Paul Mueller撰写]

    Sepmer Fi
  • 在任何地方部署Kubernetes

    容器提供了将应用程序及其依赖关系与操作系统解耦的能力。通过与虚拟机镜像相同的不打包操作系统的方式,容器可以节省大量的系统资源:计算,内存和磁盘空间。容器的下载,...

    Sepmer Fi
  • 控制MongoDB中的集群分片

    分片标记是MongoDB 2.2.0版中的一项新功能。它应该强制写入到本地数据中心,但也可以用来将集合固定到一个分片或一组分片。

    Hero
  • ElasticSearch里面的偏好查询

    我是攻城师
  • ES存在unassinged shard的调试方式

    YG
  • 安装单机版Consul

    •下载最新稳定版:https://www.consul.io/downloads.html[1]•下载指定版本:https://releases.hashico...

    用户1516716
  • 层次分划—双向指示种分析(TWINSPAN)及其在R中的计算

    与层次聚合分类相比,层次分划(hierarchical divisive)是采用“自顶向下”的分拆策略的层次聚类方法。层次分划从总体开始,逐步一分为二,直到根据...

    用户7585161
  • Object 类型

    ECMAScript中大多数的引用类型都值都是Object类型的实例,Object也是使用最多的一个类型,主要用来在程序中存储和传输数据

    河岸飞流
  • 突破Java面试(14)-分布式搜索引擎的架构

    但现在不问了,因为现在项目基本都是采用基于 lucene 的分布式搜索引擎—— ElasticSearch.

    JavaEdge

扫码关注云+社区

领取腾讯云代金券