想学习一下集群的思想和思路,我在一台Windows机器下搭建了一个 Replica Sets + Sharding 测试集群环境。
概念说明
Replica Set
副本集。简单的说集群中包含了多份数据,保证主节点挂掉了,备用节点继续提供数据服务。使用Replica Set来实现读写分离,通过在连接时指定或者在主库指定slaveOk,由Secondary来分担读的压力,Primary只承担写操作。
副本集使其组内的每个成员(member)在不同的mongod实例中具有相同的数据备份,这样可以将来自应用服务器的请求访问(request visit)得以均匀的分布在Replica Set的每一个成员所在的mongod实例上,用以减缓单台mongod服务器在请求负载上的压力。在一定时限内Replica Set能完成其组内成员数据的最终一致,这种备份机制是自动且对用户透明的。
详细请参考:Replication Introduction
Sharding
Sharding is a method for storing data across multiple machines. MongoDB uses sharding to support deployments with very large data sets and high throughput operations.
详细请参考:Sharding Introduction
- Shard:
使用 Replica Sets确保每个数据节点都具有备份、自动容错转移、自动恢复能力。mongod实例,用于存储实际的数据块,实际生产环境中一个Shard Server角色可由几台机器组个一个Replica Set承担,防止主机单点故障。 - Config:
使用3个配置服务器确保元数据完整性。mongod实例,存储了整个Cluster Metadata,其中包括Chunk信息。 - Route:
使用3个路由进程实现负载平衡提高客户端接入性能。mongos实例,前端路由,客户端由此接入,且让整个集群看上去像单一数据库,前端应用可以透明使用。
集群环境
只有一台windows机器,配置方案:
分片复本集A(三个分片节点构成一个复本集):
127.0.0.1:10000 127.0.0.1:10001 127.0.0.1:10002
分片复本集B(三个分片节点构成一个复本集):
127.0.0.1:20000 127.0.0.1:20001 127.0.0.1:20002
Configsvc(三个配置服务器节点):
127.0.0.1:30000 127.0.0.1:30001 127.0.0.1:30002
mongos(路由节点):
127.0.0.1:40000
实现步骤
创建数据和日志目录
数据文件目录
data/shard1/r0
data/shard1/r1
data/shard1/r2
data/shard2/r0
data/shard2/r1
data/shard2/r2
data/configsvr/r0
data/configsvr/r1
data/configsvr/r2
日志文件目录
log/shard1
log/shard2
log/configsvr
创建分片和复本集
配置第一组(副本集-Shard1)
启动mongod shard11进程
1
D:\mongodb\bin>mongod.exe --logpath d:/mongodb/log/shard1/r0.log --logappend --dbpath d:/mongodb/data/shard1/r0 --port 10000 --shardsvr --replSet shard1
启动mongod shard12进程
1
D:\mongodb\bin>mongod.exe --logpath d:/mongodb/log/shard1/r1.log --logappend --dbpath d:/mongodb/data/shard1/r1 --port 10001 --shardsvr --replSet shard1
启动mongod shard13进程
1
D:\mongodb\bin>mongod.exe --logpath d:/mongodb/log/shard1/r2.log --logappend --dbpath d:/mongodb/data/shard1/r2 --port 10002 --shardsvr --replSet shard1
初始化复本集
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27D:\mongodb\bin>mongo 127.0.0.1:10000/admin
MongoDB shell version: 2.6.5
connecting to: 127.0.0.1:10000/admin
> config={_id: 'shard1', members:[{_id: 0,host:'127.0.0.1:10000'},{_id:1,host:'1
27.0.0.1:10001'},{_id:2,host:'127.0.0.1:10002'}]}
{
"_id" : "shard1",
"members" : [
{
"_id" : 0,
"host" : "127.0.0.1:10000"
},
{
"_id" : 1,
"host" : "127.0.0.1:10001"
},
{
"_id" : 2,
"host" : "127.0.0.1:10002"
}
]
}
> rs.initiate(config)
{
"info" : "Config now saved locally. Should come online in about a minute.",
"ok" : 1
}
配置第二组(副本集-Shard2)
启动mongod shard21进程
1
D:\mongodb\bin>mongod.exe --logpath d:/mongodb/log/shard2/r0.log --logappend --dbpath d:/mongodb/data/shard2/r0 --port 20000 --shardsvr --replSet shard2
启动mongod shard22进程
1
D:\mongodb\bin>mongod.exe --logpath d:/mongodb/log/shard2/r1.log --logappend --dbpath d:/mongodb/data/shard2/r1 --port 20001 --shardsvr --replSet shard2
启动mongod shard23进程
1
D:\mongodb\bin>mongod.exe --logpath d:/mongodb/log/shard2/r2.log --logappend --dbpath d:/mongodb/data/shard2/r2 --port 20002 --shardsvr --replSet shard2
初始化复本集
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26D:\mongodb\bin>mongo 127.0.0.1:20000/admin
MongoDB shell version: 2.6.5
connecting to: 127.0.0.1:20000/admin
> config={_id: 'shard2', members:[{_id: 0,host:'127.0.0.1:20000'},{_id:1,host:'127.0.0.1:20001'},{_id:2,host:'127.0.0.1:20002'}]}
{
"_id" : "shard2",
"members" : [
{
"_id" : 0,
"host" : "127.0.0.1:20000"
},
{
"_id" : 1,
"host" : "127.0.0.1:20001"
},
{
"_id" : 2,
"host" : "127.0.0.1:20002"
}
]
}
> rs.initiate(config)
{
"info" : "Config now saved locally. Should come online in about a minute.",
"ok" : 1
}
启动三个配置服务节点Configsvr
1 | D:\mongodb\bin>mongod.exe --configsvr --logpath d:/mongodb/log/configsvr/r0.log --logappend --dbpath d:/mongodb/data/configsvr/r0 --port 30000 |
1 | D:\mongodb\bin>mongod.exe --configsvr --logpath d:/mongodb/log/configsvr/r1.log --logappend --dbpath d:/mongodb/data/configsvr/r1 --port 30001 |
1 | D:\mongodb\bin>mongod.exe --configsvr --logpath d:/mongodb/log/configsvr/r2.log --logappend --dbpath d:/mongodb/data/configsvr/r2 --port 30002 |
启动路由节点mongos
1 | D:\mongodb\bin>mongos.exe --configdb 127.0.0.1:30000,127.0.0.1:30001,127.0.0.1:30002 --logpath d:/mongodb/log/mongos.log --logappend --port 40000 |
配置分片
1 | D:\mongodb\bin>mongo 127.0.0.1:40000/admin |
对数据库启用分片1
2mongos> db.runCommand({"enablesharding":"sharding"})
{ "ok" : 1 }
对数据库下面的表,启用分片–按照’_id’列进行分片1
2mongos> db.runCommand({shardcollection: "sharding.testing", key: {_id:1}})
{ "collectionsharded" : "sharding.testing", "ok" : 1 }
配置到这里,集群搭建完毕了!真是不容易啊!!!
配置验证
我们来验证下配置的情况,添加10000条数据到数据库中。1
2
3
4
5
6
7D:\mongodb\bin>mongo 127.1.1.1:40000/admin
MongoDB shell version: 2.6.5
connecting to: 127.1.1.1:10000/admin
mongos> use sharding
switched to db sharding
mongos> for(var i = 1; i<=10000; i++) db.testing.save( {name: 'sharding' + i})
WriteResult({ "nInserted" : 1 })
查看分片状态(我没有限制chunk大小,数据都存在了Shard2中)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58mongos> use sharding
switched to db sharding
mongos> db.testing.stats()
{
"sharded" : true,
"systemFlags" : 1,
"userFlags" : 1,
"ns" : "sharding.testing",
"count" : 10000,
"numExtents" : 8,
"size" : 480048,
"storageSize" : 1392640,
"totalIndexSize" : 343392,
"indexSizes" : {
"_id_" : 343392
},
"avgObjSize" : 48.0048,
"nindexes" : 1,
"nchunks" : 2,
"shards" : {
"shard1" : {
"ns" : "sharding.testing",
"count" : 0,
"size" : 0,
"storageSize" : 696320,
"numExtents" : 4,
"nindexes" : 1,
"lastExtentSize" : 524288,
"paddingFactor" : 1,
"systemFlags" : 1,
"userFlags" : 1,
"totalIndexSize" : 8176,
"indexSizes" : {
"_id_" : 8176
},
"ok" : 1
},
"shard2" : {
"ns" : "sharding.testing",
"count" : 10000,
"size" : 480048,
"avgObjSize" : 48,
"storageSize" : 696320,
"numExtents" : 4,
"nindexes" : 1,
"lastExtentSize" : 524288,
"paddingFactor" : 1,
"systemFlags" : 1,
"userFlags" : 1,
"totalIndexSize" : 335216,
"indexSizes" : {
"_id_" : 335216
},
"ok" : 1
}
},
"ok" : 1
}
后记
配置完了会有“MongoDB的“not master and slaveok=false”错误。
因为SECONDARY是不允许读写的, 在写多读少的应用中,使用Replica Sets来实现读写分离。通过在连接时指定或者在主库指定slaveOk,由Secondary来分担读的压力,Primary只承担写操作。
对于replica set 中的secondary 节点默认是不可读的,我们要去从机上执行以下命令:1
SECONDARY> db.getMongo().setSlaveOk()