MongoDB 分片集群部署

最近抽了点时间整理一年前做过的MongoDB分片集群部署,具体如有图并结合下述案例分析:

cluster

分片集群配置

Shard Server: mongod实例,用于存储实际的数据块,实际生产环境中一个Shard Server角色可由几台机器组和一个Replica Set承担,防止主机单点故障。

Config Server: mongod实例,存储了整个Cluster Metadata,其中包括Chunk信息。

Route Server: mongos实例,前端路由,客户端由此接入,且让整个集群看上去像单一数据库,前端应用可以透明使用。

主要思路如下:

分片

3个分片Sharding,每一个分片由3个节点构成1主2备的Replica Set

分片复本集shard1(三个分片节点构成一个复本集):127.0.0.1:10001、127.0.0.1:10002、127.0.0.1:10003

分片复本集shard2(三个分片节点构成一个复本集):127.0.0.1:20001、127.0.0.1:20002、127.0.0.1:20003

分片复本集shard3(三个分片节点构成一个复本集):127.0.0.1:30001、 127.0.0.1:30002、 127.0.0.1:30003

配置节点

Configsvr(三个配置服务器节点):127.0.0.1:10004、127.0.0.1:20004、127.0.0.1:30004

路由节点

1个路由节点Mongos
Mongos(一个路由节点):127.0.0.1:27017

搭建集群

创建Sharding和Replica Set
创建并配置第一组
1
2
3
mongod --dbpath=H:\wamp\www\MongoDB_Cluster\MongoDB_1\db\shard11 --journal --logpath=H:\wamp\www\MongoDB_Cluster\MongoDB_1\logs\shard11.log --logappend --directoryperdb --port 10001 --replSet shard1/127.0.0.1:10002 --oplogSize 100 --rest --shardsvr &
mongod --dbpath=H:\wamp\www\MongoDB_Cluster\MongoDB_1\db\shard12 --journal --logpath=H:\wamp\www\mongoDB_Cluster\MongoDB_1\logs\shard12.log --logappend --directoryperdb --port 10002 --replSet shard1/127.0.0.1:10003 --oplogSize 100 --rest --shardsvr &
mongod --dbpath=H:\wamp\www\MongoDB_Cluster\MongoDB_1\db\shard13 --journal --logpath=H:\wamp\www\mongoDB_Cluster\MongoDB_1\logs\shard13.log --logappend --directoryperdb --port 10003 --replSet shard1/127.0.0.1:10001 --oplogSize 100 --rest --shardsvr &

启动并配置shard1

1
2
3
4
5
mongo 127.0.0.1:10001/admin
config={_id:'shard1',members:[{_id:0,host:'127.0.0.1:10001'},{_id:1,host:'127.0.0.1:10002'}]}//分片组配置信息
rs.initiate(config);//初始化分片shard1
rs.addArb('127.0.0.1:10003');//添加仲裁机
rs.status();服务器down机之后可以加上--logappend参数复写日志

创建并配置第二组
1
2
3
mongod --dbpath=H:\wamp\www\mongoDB_Cluster\MongoDB_2\db\shard21 --journal --logpath=H:\wamp\www\mongoDB_Cluster\MongoDB_2\logs\shard21.log --logappend --directoryperdb --port 20001 --replSet shard2/127.0.0.1:20002 --oplogSize 100 --rest --shardsvr &
mongod --dbpath=H:\wamp\www\mongoDB_Cluster\MongoDB_2\db\shard22 --journal --logpath=H:\wamp\www\mongoDB_Cluster\MongoDB_2\logs\shard22.log --logappend --directoryperdb --port 20002 --replSet shard2/127.0.0.1:20003 --oplogSize 100 --rest --shardsvr &
mongod --dbpath=H:\wamp\www\mongoDB_Cluster\MongoDB_2\db\shard23 --journal --logpath=H:\wamp\www\mongoDB_Cluster\MongoDB_2\logs\shard23.log --logappend --directoryperdb --port 20003 --replSet shard2/127.0.0.1:20001 --oplogSize 100 --rest --shardsvr &

启动并配置shard2

1
2
3
4
5
mongo 127.0.0.1:20001/admin
config={_id:'shard2',members:[{_id:0,host:'127.0.0.1:20001'},{_id:1,host:'127.0.0.1:20002'}]}//分片组配置信息
rs.initiate(config);//初始化分片shard2
rs.addArb('127.0.0.1:20003');//添加仲裁机
rs.status();//查看状态

创建并配置第三组
1
2
3
mongod --dbpath=H:\wamp\www\mongoDB_Cluster\MongoDB_3\db\shard31 --journal --logpath=H:\wamp\www\mongoDB_Cluster\MongoDB_3\logs\shard31.log --logappend --directoryperdb --port 30001 --replSet shard3/127.0.0.1:30002 --oplogSize 100 --rest --shardsvr &
mongod --dbpath=H:\wamp\www\mongoDB_Cluster\MongoDB_3\db\shard32 --journal --logpath=H:\wamp\www\mongoDB_Cluster\MongoDB_3\logs\shard32.log --logappend --directoryperdb --port 30002 --replSet shard3/127.0.0.1:30003 --oplogSize 100 --rest --shardsvr &
mongod --dbpath=H:\wamp\www\mongoDB_Cluster\MongoDB_3\db\shard33 --journal --logpath=H:\wamp\www\mongoDB_Cluster\MongoDB_3\logs\shard33.log --logappend --directoryperdb --port 30003 --replSet shard3/127.0.0.1:30001 --oplogSize 100 --rest --shardsvr &

启动并配置shard3

1
2
3
4
5
mongo 127.0.0.1:30001/admin
config={_id:'shard3',members:[{_id:0,host:'127.0.0.1:30001'},{_id:1,host:'127.0.0.1:30002'}]}//分片组配置信息
rs.initiate(config);//初始化分片shard3
rs.addArb('127.0.0.1:30003');//添加仲裁机
rs.status();

启动三个配置服务节点Configsvr
1
2
3
mongod --dbpath=H:\wamp\www\mongoDB_Cluster\MongoDB_1\db\config --port 10004 --journal --logpath=H:\wamp\www\mongoDB_Cluster\MongoDB_1\logs\config.log --logappend --directoryperdb --oplogSize 100 --rest --configsvr &
mongod --dbpath=H:\wamp\www\mongoDB_Cluster\MongoDB_2\db\config --port 20004 --journal --logpath=H:\wamp\www\mongoDB_Cluster\MongoDB_2\logs\config.log --logappend --directoryperdb --oplogSize 100 --rest --configsvr &
mongod --dbpath=H:\wamp\www\mongoDB_Cluster\MongoDB_3\db\config --port 30004 --journal --logpath=H:\wamp\www\mongoDB_Cluster\MongoDB_3\logs\config.log --logappend --directoryperdb --oplogSize 100 --rest --configsvr &
启动一个路由点Mongos
1
mongos --configdb 127.0.0.1:10004,127.0.0.1:20004,127.0.0.1:30004 -port 27017 -chunkSize 100 --logpath=H:\wamp\www\mongoDB_Cluster\Mongos\logs\mongos.log --logappend &
配置分片
1
2
3
4
mongo 127.0.0.1:27017/admin
db.runCommand({addshard:"shard1/127.0.0.1:10001,127.0.0.1:10002,127.0.0.1:10003",name:"shard1"})
db.runCommand({addshard:"shard2/127.0.0.1:20001,127.0.0.1:20002,127.0.0.1:20003",name:"shard2"})
db.runCommand({addshard:"shard3/127.0.0.1:30001,127.0.0.1:30002,127.0.0.1:30003",name:"shard3"})
查看配置结果
1
db.runCommand({listshards: 1})

如果不激活数据库分片,数据库只会存在一个Shard中,一旦激活数据库分片,数据库中不同的Collection将被存放在不同的Shard上,但一个Collection仍旧存放在同一个Shard上,要使单个Collection也分片,还需单独对Collection作些操作

1
db.runCommand({enablesharding:"mongotest"})

要使单个Collection也分片存储,需要给Collection指定一个分片key,通过以下命令操作:

1
db.runCommand({shardcollection:"mongotest.datatest",key:{intdata:1}})

查看Collection分片信息

1
2
3
use mongotest
for (var i = 1; i <= 100000; i++) db.datatest.save({intdata:1,stringdata:'这是第'+i+'条测试数据',time:new Date()});
db.datatest.stats();

集群中出现问题处理:

Mongos节点宕机

一个Mongos进程应该运行在每一个应用程序服务器上,这个服务器应该独占这个Mongos进程,并且通过它与分片集群来通讯。
Mongos进程不是持久化的,相反,它们在启动的时候从Config Server上收集所有必须的配置信息。这表明,任何一个应用程序服务器节点故障,对作为一个整体的分片集群来讲并没有什么影响,所有别的应用程序服务器将依然是继续正常工作。在这种情况下,恢复是一个相当简单的事情,我们只需要去启动一个新的应用程序服务器和一个新的Mongos进程即可。

分片中的某一个Mongod节点宕机

每一个分片由n个服务器构成,这n个服务器被配置为一个复制集(replica set)。如果在复制集中的任何一个节点宕机,在这个分片上读与写操作任然是允许的。更加重要的是,宕机服务器上的数据都不会丢失,因为复制机制存在一个选项,那就是强制复制写操作到分片的其它节点上再返回,这与在Dynamo上设置write=2类似。在MongoDB v1.6以后版本中Replica sets才是可用的。

分片中的所有Mongod节点宕机

如果一个分片中的全部节点(replicas)都宕机了,在该分片内的数据将不能被访问。然而,操作任然是继续进行,只不过是由别的分片分担。看文档就可以弄清楚为什么这样。如果分片被配置为一个复制集(Replicas set),至少一个成员应该在另外一个数据中心,那样的话,整个分片都宕机几乎是不可能的。为了有更大的冗余度,推荐这样进行配置。

一个Config Server宕机

一个产品级的分片集群需要有3个Config Server进程,每一个进程都在一台独立的机器上运行。对于Config server中的集群元数据的写操作使用一个两阶段提交,去确保是一个原子的并且是被复制的事务操作。
在任何一个配置服务器失效的时候,Mongodb集群的元数据都会变成为只读了。集群系统继续运行,但是chunks在一个分片中将会成为不可以被拆分或者是不可以跨分片进行迁移。对于大多数使用场景,这个不会导致问题,应为改变Chunk元数据进行的并不频繁。

另外,使宕机的Config Server在一个合理的时间周期(一天)内恢复是相当重要的,这样可以避免分片由于缺乏迁移而变得负载不均衡(相对而言,对于大多数产品场景,这种现象也不是很严重的事情)。

如需MongoDB客户端工具,强烈推荐MongoVUE,但由于高版本并不支持长期免费试用,因此只能破解原生版本,如有需要,可以移步mongoVUE1.5完全破解版赠送 获取。

(The End)

坚持原创技术分享,您的支持将鼓励我继续创作!