MongoDB3.2集群搭建

0x00 前言

  MongoDB分布式集群搭建比较容易实现,为了优化项目的性能,实战并记录一下过程,更多信息参考官方文档

0x01 原理介绍

1.1水平扩展和垂直扩展

1.水平扩展也叫横向扩展,通过提高CPU、内存的能力。(比方:钢铁侠抬起一辆车)
2.垂直扩展也叫纵向扩展或者分片(shard),通过分割数据到不同的服务器,利用多台低存储、低内存的机器共同完成大数据的处理。(比方:十个人抬起一辆车)
  如果有1T的数据需要存储,可以通过买1T的硬盘,实现单服务器存储,也可以通过4台256G硬盘的服务器实现分布式存储,如下图:

sharding

1.2mongodb集群组件

mongodb集群组件
1.分片(shard):是一个单独的mongod服务器或者复制集,存储集群的部分数据。
2.路由(mongos)根据应用请求分发读写请求信息到各个分片
3.配置服务器(config server):存储数据分片信息,配置服务器如果宕机,整个集群处于不可用状态。
注:生产环境中,为了提高容错能力和抗灾能力,配置服务器应该为复制集且为多台、mongos也应对于两台、分片均采用复制集

0x02 搭建实战

此次集群搭建实战基于一台主机之上,原理和多台主句上搭建一样。多台主机搭建要求分片服务器与配置服务器和mongos能相互访问。可参考官方快速部署

2.1环境与系统框架图

2.1.1搭建环境

  Ubuntu 14.04
  MongoDB 3.2.6
注:3.2.6修复了3.2.5及以前版本的shards 大数据分片“30 second network timeout”的bug

2.1.2系统框架图

系统框架图

2.2建立数据库目录

1
2
3
4
5
#三个分片目录和一个配置服务器目录
mkdir /data/db1
mkdir /data/db2
mkdir /data/db3
mkdir /data/configdb

2.3启动分片和config server

1
2
3
4
5
mongod --port 10001 --dbpath /data/db1&
mongod --port 10002 --dbpath /data/db2&
mongod --port 10003 --dbpath /data/db3&
mongod --configsvr&
#利用"&"将mongod后台运行,也可以打开多个窗口单独运行mongod。

注:笔者在某教材上看到:“–configsvr设置端口为27017,数据位置为/data/configdb 可以用–port 27019 –dbpath /data/configdb代替”,然而使用后者连接mongos,查看sh.status()会报如下错误

mongos上执行sh.status()
亲测这个报错问题可以mongo连接配置服务器执行sh.status()解决,不过最好还是使用官方”–configsvr”吧!

2.4启动mongos

开启一个新的窗口,由于mongos需要读取配置服务器的信息,配置服务器一定要在mongos之前运行

1
2
#连接配置服务器,config server默认监听27019端口,mongos默认监听27017端口
mongos --configdb 127.0.0.1:27019

2.5配置集群

再开启一个新的窗口

2.5.1连接mongos

1
2
#服务器上运行mongo默认连接127.0.0.1:27017
mongo

2.5.2添加分片

1
2
3
sh.addShard("127.0.0.1:10001")
sh.addShard("127.0.0.1:10002")
sh.addShard("127.0.0.1:10003")

如下图:

addShard

2.5.3数据分片

(1)启用数据库的分片

1
sh.enableSharding("test")

(2)对集合数据分片

1
2
#注意:如果对已存在的集合分片,片键(此为uaername)必须是已经建立索引
sh.shardCollection("test.student",{"username":1})

2.5.4集群状态监控

1
2
3
4
#连接mongos
mongo --port 27017
sh.status()
#如果分片信息较多,只显示部分信息,sh.status({"verbose":1})可以完全显示

可以获得分片的信息,如图:

sh.status()
至此,一个单机版的mongodb集群搭建完毕,应用连接mongos可以按照操作普通mongod的方式操作mongos,从而进行备份恢复数据库、数据插入和获取等。

0x03 集群的其他操作

3.1 从集群中删除分片

3.1.1连接到mongos

1
2
3
mongo
use admin
db.runCommand( { removeShard: "shard000" } )

立刻得到如下信息

1
2
3
4
5
6
{
"msg" : "draining started successfully",
"state" : "started",
"shard" : "shard000",
"ok" : 1
}

但是分片删除操作没有完成,需要将删除分片上的所有数据迁移到其他的分片,可能会花费很长的时间(如果只有最后一个分片,禁止删除分片操作)
此时如果尝试删除其他分片,例如:执行db.runCommand( { removeShard: "shard001" } )会报错,提示不能同时删除多个分片

1
2
3
"ok" : 0,
"errmsg" : "Can't have more than one draining shard at a time",
"code" : 117

3.1.2一段时间之后,运行db.runCommand( { removeShard: "shard000" } )检查数据迁移状态,返回如下

1
2
3
4
5
6
7
8
9
10
11
12
13
{
"msg" : "draining ongoing",
"state" : "ongoing",
"remaining" : {
"chunks" : NumberLong(0),
"dbs" : NumberLong(1)
},
"note" : "you need to drop or movePrimary these databases",
"dbsToMove" : [
"test_admin"
],
"ok" : 1
}

其中的remainning是必须迁移到其他分片剩余的数据块(chunks)和这个分片上未分片(primary)的数据库数量

3.1.3直到chunks为零以后,将未分片的数据迁移到其他分片(可能会花费一定的时间),倘若该数据库没用也可直接删除

1
db.runCommand( { movePrimary: "test_admin", to: "shard0001" })

迁移成功后返回如下:

1
{ "primary" : "shard0001:127.0.0.1:100002", "ok" : 1 }

3.1.4完成上一步之后再次执行db.runCommand( { removeShard: "shard000" } ),得到如下返回即为成功删除该分片

1
2
3
4
5
6
{
"msg" : "removeshard completed successfully",
"state" : "completed",
"shard" : "shard0001",
"ok" : 1
}

3.2均衡器配置

3.2.1均衡器的操作

由于均衡器工作时会影响性能,通常在操作前关闭均衡器,操作之后再开启均衡器(备份期间要保证均衡过程一定不能运行)
1.查看均衡器状态:sh.getBalancerState()
2.开启均衡器:sh.setBalancerState(true)
3.关闭均衡器:sh.setBalancerState(false)或者sh.stopBalancer()

3.2.2检查均衡锁的状态

连接mongos,切换到config库,执行命令,过程如下(也可以通过sh.status()的balancer字段判断)

1
2
3
mongo
use config
db.locks.find( { _id : "balancer" } ).pretty()

返回如下信息

1
2
3
4
5
6
7
8
9
{
"_id" : "balancer",
"state" : 0,
"who" : "localhost:27017:1469031212:1501674588:Balancer:1603386966",
"ts" : ObjectId("578fde70a8fc7b3ad5b2635d"),
"process" : "localhost:27017:1469031212:1501674588",
"when" : ISODate("2016-07-20T20:26:24.238Z"),
"why" : "doing balance round"
}

其中state 值为0表明不存在锁;在mongos2.0以后版本,值为2表明存在锁,之前的版本,值为 1 表明存在锁