前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >浅尝辄止MongoDB:分片

浅尝辄止MongoDB:分片

作者头像
用户1148526
发布2019-05-25 19:35:35
5230
发布2019-05-25 19:35:35
举报
文章被收录于专栏:Hadoop数据仓库Hadoop数据仓库

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://cloud.tencent.com/developer/article/1433063

目录

一、架构

二、配置

1. 启动配置服务器

2. 启动分片控制器

3. 启动两个分片服务器

4. 在分片控制器中添加分片

5. 设置块大小

6. 创建分片集合

7. 向分片添加数据

三、维护

1. 添加新分片

2. 删除分片


代码语言:txt
复制
    大部分摘自《MongoDB大数据处理权威指南》(第3版)。
代码语言:txt
复制
    使用MongoDB时,水平数据分割是唯一可采用的方式。MongoDB使用一种唯一的方法用于分片,由MongoS路径进程管理数据的分割,并将请求路由到必须的分片服务器。如果查询需要访问多个分片中的数据,MongoS将管理从多个分片获取数据并将数据合并成单个游标的过程。
代码语言:txt
复制
    分片需求:
  1. 具有将数据平均分散到所有分片的能力。
  2. 以容错方式存储分片数据的能力。
  3. 在系统运行时添加或删除分片的能力。

一、架构

代码语言:txt
复制
    MongoDB使用代理机制实现分片(如图1所示);其中的mongos守护进程将作为多个基于mongod的分片服务器的控制器。当应用连接到mongos时,将把这些分片服务器当作单个MongoDB数据库服务器;此后,应用将把它的所有命令(例如更新、查询和删除)都发送到mongos进程。

图1 不使用冗余时的简单分片设置

代码语言:txt
复制
    进程mongos负责管理应用发送到MongoDB服务器的所有命令,并且该守护进程将重新发送跨多个分片的查询到多个服务器,再将结果聚集在一起。
代码语言:txt
复制
    MongoDB在集合级别实现分片,而不是数据库级别。在许多系统中,只有一个或两个集合可以增长到需要使用分片的地步。因此应该理智地使用分片;如果不需要的话,就不要为较小的集合增加管理分布数据的开销。
代码语言:txt
复制
    分片系统使用分片键将数据映射到块,块是文档键的逻辑连续范围。每个块标志着分片键值特定连续范围内的许多文档;这些值使mongos控制器可以快速找到包含它所需的文档的块。然后MongoDB分片系统将把块存储在可用的分片系统中;配置服务器将记录每个块存储的分片服务器的位置。这是分片实现的一个重要特性,因为通过它可以从集合中添加和删除分片,而不需要备份和恢复数据。
代码语言:txt
复制
    当在集群中添加新的分片时,该系统将会把许多块迁移到新的服务器集合中,从而平均地分散数据。类似地,从集群中删除分片时,分片控制器将会从即将离线的分片中抽取所有的块,并重新将它们分散到剩下的分片服务器中。

MongoDB的分片设置还需要存储分片服务器的配置,以及集群中每个分片服务器的信息。为了支持该功能,需要使用一台称为配置服务器的MongoDB服务器;该服务器实例是一个以特殊角色运行的mongod服务器。正如之前解释的,配置服务器还可以用作目录,通过它可以找到每个块的位置。在集群中可以具有1台(开发)或3台(生产)配置服务器。推荐在生产环境中使用3台配置服务器,因为配置服务器的崩溃将意味着无法决定分片数据存储在哪个分片中。

代码语言:txt
复制
    可以将多个不同服务的实例添加到同一服务器中。图2显示了一个完全冗余的分片系统,它将为分片存储和配置服务器使用副本集,并且使用一组mongos管理集群。它还显示了如何将这些服务以密集的方式运行在3台物理服务器中。

图2 冗余分片配置

二、配置

代码语言:txt
复制
    测试环境:
代码语言:txt
复制
     分片控制器(mongos):hdp4:27017
代码语言:txt
复制
     配置服务器(mongod):hdp3:27017
代码语言:txt
复制
              分片0(mongod):hdp2:27017
代码语言:txt
复制
              分片1(mongod):hdp1:27017

1. 启动配置服务器

代码语言:txt
复制
    配置文件/home/mongodb/mongodb-4.0.2/mongodb.conf内容如下:
代码语言:javascript
复制
logpath = /home/mongodb/mongodb-4.0.2/data/mongodb.log
pidfilepath = /home/mongodb/mongodb-4.0.2/data/mongodb.pid
dbpath = /home/mongodb/mongodb-4.0.2/data/
bind_ip_all = true
configsvr = true
replSet = configs
port = 27017
代码语言:txt
复制
    其中configsvr参数指定该服务器为分片的配置服务器,replSet指定副本集名称为configs。
代码语言:txt
复制
    启动实例:
代码语言:javascript
复制
mongod -f /home/mongodb/mongodb-4.0.2/mongodb.conf &
代码语言:txt
复制
    副本集初始化,并向副本集中添加服务器:
代码语言:javascript
复制
$ mongo
> rs.initiate();
{
    "info2" : "no configuration specified. Using a default configuration for the set",
    "me" : "hdp3:27017",
    "ok" : 1,
    "operationTime" : Timestamp(1539908963, 1),
    "$gleStats" : {
        "lastOpTime" : Timestamp(1539908963, 1),
        "electionId" : ObjectId("000000000000000000000000")
    },
    "lastCommittedOpTime" : Timestamp(0, 0),
    "$clusterTime" : {
        "clusterTime" : Timestamp(1539908963, 1),
        "signature" : {
            "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
            "keyId" : NumberLong(0)
        }
    }
}
configs:SECONDARY>

2. 启动分片控制器

代码语言:txt
复制
    配置文件/home/mongodb/mongodb-4.0.2/mongodb.conf内容如下:
代码语言:javascript
复制
logpath = /home/mongodb/mongodb-4.0.2/data/mongodb.log
pidfilepath = /home/mongodb/mongodb-4.0.2/data/mongodb.pid
bind_ip_all = true
configdb = configs/hdp3:27017
代码语言:txt
复制
    其中configdb参数指定配置服务器,格式为“副本集名称/配置服务器主机名:端口”
代码语言:txt
复制
    启动实例:
代码语言:javascript
复制
mongos -f /home/mongodb/mongodb-4.0.2/mongodb.conf &

3. 启动两个分片服务器

代码语言:txt
复制
    配置文件/home/mongodb/mongodb-4.0.2/mongodb.conf内容如下:
代码语言:javascript
复制
logpath = /home/mongodb/mongodb-4.0.2/data/mongodb.log
pidfilepath = /home/mongodb/mongodb-4.0.2/data/mongodb.pid
dbpath = /home/mongodb/mongodb-4.0.2/data/
bind_ip_all = true
port=27017
shardsvr=true
代码语言:txt
复制
    分别在hdp2、hdp1上启动分片实例:
代码语言:javascript
复制
mongod -f /home/mongodb/mongodb-4.0.2/mongodb.conf &

4. 在分片控制器中添加分片

代码语言:javascript
复制
$ mongo hdp4:27017
mongos> use admin;
switched to db admin
mongos> sh.addShard("hdp2:27017");
{
    "shardAdded" : "shard0000",
    "ok" : 1,
    "operationTime" : Timestamp(1539909528, 4),
    "$clusterTime" : {
        "clusterTime" : Timestamp(1539909528, 4),
        "signature" : {
            "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
            "keyId" : NumberLong(0)
        }
    }
}
mongos> sh.addShard("hdp1:27017");
{
    "shardAdded" : "shard0001",
    "ok" : 1,
    "operationTime" : Timestamp(1539909542, 2),
    "$clusterTime" : {
        "clusterTime" : Timestamp(1539909542, 2),
        "signature" : {
            "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
            "keyId" : NumberLong(0)
        }
    }
}
mongos>
代码语言:txt
复制
    两台分片服务器现在已经被激活,下面检查分片服务器的状态:
代码语言:javascript
复制
mongos> sh.status();
--- Sharding Status --- 
  sharding version: {
      "_id" : 1,
      "minCompatibleVersion" : 5,
      "currentVersion" : 6,
      "clusterId" : ObjectId("5bc92565577f5a97a8441de1")
  }
  shards:
        {  "_id" : "shard0000",  "host" : "hdp2:27017",  "state" : 1 }
        {  "_id" : "shard0001",  "host" : "hdp1:27017",  "state" : 1 }
  active mongoses:
        "4.0.2" : 1
  autosplit:
        Currently enabled: yes
  balancer:
        Currently enabled:  yes
        Currently running:  no
        Failed balancer rounds in last 5 attempts:  0
        Migration Results for the last 24 hours: 
                No recent migrations
  databases:
        {  "_id" : "config",  "primary" : "config",  "partitioned" : true }

mongos>
代码语言:txt
复制
    现在分片环境已经可以正常运行,但还没有分片数据。

5. 设置块大小

代码语言:javascript
复制
$ mongo hdp4:27017
mongos> use config;
switched to db config
mongos> db.settings.save({"_id":"chunksize","value":1});
WriteResult({ "nMatched" : 0, "nUpserted" : 1, "nModified" : 0, "_id" : "chunksize" })
mongos>
代码语言:txt
复制
    设置块大小为1M是方便实验,不然就需要插入大量数据。

6. 创建分片集合

代码语言:txt
复制
    创建一个名为testdb的数据库,然后在该数据库中激活一个名为testcollection的集合,赋予它一个名为testkey的参数,用作分片键:
代码语言:javascript
复制
$ mongo hdp4:27017
mongos> use admin;
switched to db admin
mongos> sh.enableSharding("testdb");
{
    "ok" : 1,
    "operationTime" : Timestamp(1539914273, 5),
    "$clusterTime" : {
        "clusterTime" : Timestamp(1539914273, 5),
        "signature" : {
            "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
            "keyId" : NumberLong(0)
        }
    }
}
mongos> show dbs
admin   0.000GB
config  0.001GB
mongos> use testdb;
switched to db testdb
mongos> db.testcollection.createIndex({"testkey":1});
{
    "raw" : {
        "hdp1:27017" : {
            "createdCollectionAutomatically" : false,
            "numIndexesBefore" : 1,
            "numIndexesAfter" : 2,
            "ok" : 1
        }
    },
    "ok" : 1,
    "operationTime" : Timestamp(1539914351, 4),
    "$clusterTime" : {
        "clusterTime" : Timestamp(1539914351, 4),
        "signature" : {
            "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
            "keyId" : NumberLong(0)
        }
    }
}
mongos> sh.shardCollection("testdb.testcollection",{"testkey":1});
{
    "collectionsharded" : "testdb.testcollection",
    "collectionUUID" : UUID("587f9db3-6217-4d17-a5a4-be128aed58d8"),
    "ok" : 1,
    "operationTime" : Timestamp(1539914504, 8),
    "$clusterTime" : {
        "clusterTime" : Timestamp(1539914504, 8),
        "signature" : {
            "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
            "keyId" : NumberLong(0)
        }
    }
}
mongos>

7. 向分片添加数据

代码语言:txt
复制
    连接控制器:
代码语言:javascript
复制
mongo hdp4:27017
代码语言:txt
复制
    插入100000条数据:
代码语言:javascript
复制
mongos> use testdb;
switched to db testdb
mongos> for(i=1;i<=100000;i++){db.testcollection.insert({"testkey":i,"name":"jack"+i})};
WriteResult({ "nInserted" : 1 })
mongos> db.testcollection.count();
100000
mongos>
代码语言:txt
复制
    连接分片查看每个分片的数据量:
代码语言:javascript
复制
mongo hdp2:27017
> use testdb;
switched to db testdb
> db.testcollection.count();
38399

mongo hdp1:27017
> use testdb;
switched to db testdb
> db.testcollection.count();
61601
代码语言:txt
复制
    注意,在每台分片服务器中可能看到不同的文档数目,这取决于检查每台分片服务器的时间。mongos实例开始会在一个分片中初始化所有的块,但随着时间的推移,将对数据集中的数据进行调整,通过移动块的方式将数据平均地分布到所有分片服务器中。因此,指定分片服务器中的记录数可能会不断变化。

三、维护

1. 添加新分片

(1)创建新的分片服务器

代码语言:txt
复制
     创建新mongod实例hdp4:27018,配置文件/home/mongodb/mongodb-4.0.2/mongodb1.conf内容如下:
代码语言:javascript
复制
logpath = /home/mongodb/mongodb-4.0.2/data1/mongodb.log
pidfilepath = /home/mongodb/mongodb-4.0.2/data1/mongodb.pid
dbpath = /home/mongodb/mongodb-4.0.2/data1/
bind_ip_all = true
port=27018
shardsvr=true
代码语言:txt
复制
    分别在hdp4上启动分片实例:
代码语言:javascript
复制
mongod -f /home/mongodb/mongodb-4.0.2/mongodb1.conf &

(2)向集群中添加新的分片

代码语言:javascript
复制
$ mongo hdp4:27017
mongos> use admin;
switched to db admin
mongos> sh.addShard("hdp4:27018");
{
    "shardAdded" : "shard0002",
    "ok" : 1,
    "operationTime" : Timestamp(1539918006, 3),
    "$clusterTime" : {
        "clusterTime" : Timestamp(1539918006, 3),
        "signature" : {
            "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
            "keyId" : NumberLong(0)
        }
    }
}
mongos>

(3)查询分片状态

代码语言:javascript
复制
mongos> sh.status();
--- Sharding Status --- 
  sharding version: {
      "_id" : 1,
      "minCompatibleVersion" : 5,
      "currentVersion" : 6,
      "clusterId" : ObjectId("5bc9389c8d2765f26c37e01d")
  }
  shards:
        {  "_id" : "shard0000",  "host" : "hdp2:27017",  "state" : 1 }
        {  "_id" : "shard0001",  "host" : "hdp1:27017",  "state" : 1 }
        {  "_id" : "shard0002",  "host" : "hdp4:27018",  "state" : 1 }
  active mongoses:
        "4.0.2" : 1
  autosplit:
        Currently enabled: yes
  balancer:
        Currently enabled:  yes
        Currently running:  no
        Failed balancer rounds in last 5 attempts:  0
        Migration Results for the last 24 hours: 
                8 : Success
  databases:
        {  "_id" : "config",  "primary" : "config",  "partitioned" : true }
                config.system.sessions
                        shard key: { "_id" : 1 }
                        unique: false
                        balancing: true
                        chunks:
                                shard0000    1
                        { "_id" : { "$minKey" : 1 } } -->> { "_id" : { "$maxKey" : 1 } } on : shard0000 Timestamp(1, 0) 
        {  "_id" : "testdb",  "primary" : "shard0001",  "partitioned" : true,  "version" : {  "uuid" : UUID("89e5f744-afca-434e-b94b-c700114f8795"),  "lastMod" : 1 } }
                testdb.testcollection
                        shard key: { "testkey" : 1 }
                        unique: false
                        balancing: true
                        chunks:
                                shard0000    4
                                shard0001    4
                                shard0002    3
                        { "testkey" : { "$minKey" : 1 } } -->> { "testkey" : 2 } on : shard0002 Timestamp(9, 0) 
                        { "testkey" : 2 } -->> { "testkey" : 18080 } on : shard0002 Timestamp(7, 0) 
                        { "testkey" : 18080 } -->> { "testkey" : 27119 } on : shard0002 Timestamp(8, 0) 
                        { "testkey" : 27119 } -->> { "testkey" : 38587 } on : shard0001 Timestamp(7, 1) 
                        { "testkey" : 38587 } -->> { "testkey" : 47626 } on : shard0000 Timestamp(6, 1) 
                        { "testkey" : 47626 } -->> { "testkey" : 57786 } on : shard0000 Timestamp(9, 1) 
                        { "testkey" : 57786 } -->> { "testkey" : 66825 } on : shard0001 Timestamp(8, 1) 
                        { "testkey" : 66825 } -->> { "testkey" : 76985 } on : shard0001 Timestamp(4, 3) 
                        { "testkey" : 76985 } -->> { "testkey" : 86024 } on : shard0000 Timestamp(5, 2) 
                        { "testkey" : 86024 } -->> { "testkey" : 96184 } on : shard0000 Timestamp(5, 3) 
                        { "testkey" : 96184 } -->> { "testkey" : { "$maxKey" : 1 } } on : shard0001 Timestamp(6, 0) 

mongos>
代码语言:txt
复制
    查询三个分片的记录数:
代码语言:javascript
复制
$ mongo hdp1:27017
> use testdb;
switched to db testdb
> db.testcollection.count();
34484
>

$ mongo hdp2:27017
> use testdb;
switched to db testdb
> db.testcollection.count();
38398
> 

$ mongo hdp4:27018
> use testdb;
switched to db testdb
> db.testcollection.count();
27118
>
代码语言:txt
复制
    分片系统将数据重新平均分布到扩展后的集群中。随着时间的推移,分片系统将从shard0和shard1存储服务器中迁移出一些块,从而将数据平均分布在组成集群的三台服务器中。该过程将自动发生,即使testcollection集合中没有新的数据插入,也会执行。在此情况下,mongos分片控制器将移动一些块到新的服务器,然后将它们注册到配置服务器中。

2. 删除分片

(1)删除分片

代码语言:javascript
复制
mongo hdp4:27017
mongos> use admin;
switched to db admin
mongos> db.runCommand({removeShard : "hdp4:27018"});
{
    "msg" : "draining started successfully",
    "state" : "started",
    "shard" : "shard0002",
    "note" : "you need to drop or movePrimary these databases",
    "dbsToMove" : [ ],
    "ok" : 1,
    "operationTime" : Timestamp(1539919362, 2),
    "$clusterTime" : {
        "clusterTime" : Timestamp(1539919362, 2),
        "signature" : {
            "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
            "keyId" : NumberLong(0)
        }
    }
}
mongos>
代码语言:txt
复制
    命令removeShard返回一条信息,表示移除已经启动。另外还表示mongos已经开始重新将目标分片服务器中的块移到集群中的其它分片服务器。该过程被称为清空分片服务器。还列出了清空过程中不能移出分片服务器的数据库,这些都在dbsToMove数组中。

(2)验证

代码语言:txt
复制
     为验证removeShard命令是否成功,可使用listshards确认目标分片服务器是否已经从集群中移除。例如,下面的输出显示之前创建的服务器shard2已经不在shards数组中:
代码语言:javascript
复制
mongo hdp4:27017
mongos> use admin;
switched to db admin
mongos> db.runCommand({listshards:1});
{
    "shards" : [
        {
            "_id" : "shard0000",
            "host" : "hdp2:27017",
            "state" : 1
        },
        {
            "_id" : "shard0001",
            "host" : "hdp1:27017",
            "state" : 1
        }
    ],
    "ok" : 1,
    "operationTime" : Timestamp(1539919761, 1),
    "$clusterTime" : {
        "clusterTime" : Timestamp(1539919761, 1),
        "signature" : {
            "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
            "keyId" : NumberLong(0)
        }
    }
}
mongos>
代码语言:txt
复制
    查询三个服务器的记录数:
代码语言:javascript
复制
$ mongo hdp1:27017
> use testdb;
switched to db testdb
> db.testcollection.count();
43524
>

$ mongo hdp2:27017
> use testdb;
switched to db testdb
> db.testcollection.count();
56476
> 

$ mongo hdp4:27018
> use testdb;
switched to db testdb
> db.testcollection.count();
0
>
代码语言:txt
复制
    此时可以终止shard2 mongod进程并删除它的存储文件,因为它的数据已经被迁移到其它服务器中。
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018年10月19日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、架构
  • 二、配置
    • 1. 启动配置服务器
      • 2. 启动分片控制器
        • 3. 启动两个分片服务器
          • 4. 在分片控制器中添加分片
            • 5. 设置块大小
              • 6. 创建分片集合
                • 7. 向分片添加数据
                • 三、维护
                  • 1. 添加新分片
                    • 2. 删除分片
                    相关产品与服务
                    云数据库 MongoDB
                    腾讯云数据库 MongoDB(TencentDB for MongoDB)是腾讯云基于全球广受欢迎的 MongoDB 打造的高性能 NoSQL 数据库,100%完全兼容 MongoDB 协议,支持跨文档事务,提供稳定丰富的监控管理,弹性可扩展、自动容灾,适用于文档型数据库场景,您无需自建灾备体系及控制管理系统。
                    领券
                    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档