MongoDB: Replica Sets + Sharding

想学习一下集群的思想和思路,我在一台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)

  1. 启动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
  2. 启动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
  3. 启动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
  4. 初始化复本集

    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
    D:\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)

  1. 启动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
  2. 启动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
  3. 启动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
  4. 初始化复本集

    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
    D:\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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
D:\mongodb\bin>mongo 127.0.0.1:40000/admin
MongoDB shell version: 2.6.5
connecting to: 127.0.0.1:40000/admin
mongos> db.runCommand({addshard:"shard1/127.0.0.1:10000,127.0.0.1:10001,127.0.0.1:10002"})
{ "shardAdded" : "shard1", "ok" : 1 }
mongos> db.runCommand({addshard:"shard2/127.0.0.1:20000,127.0.0.1:20001,127.0.0.1:20002"})
{ "shardAdded" : "shard2", "ok" : 1 }
mongos> printShardingStatus()
--- Sharding Status ---
sharding version: {
"_id" : 1,
"version" : 4,
"minCompatibleVersion" : 4,
"currentVersion" : 5,
"clusterId" : ObjectId("563af622785bc1d504c2393c")
}
shards:
{ "_id" : "shard1", "host" : "shard1/127.0.0.1:10000,127.0.0.1:10001,127.0.0.1:10002" }
{ "_id" : "shard2", "host" : "shard2/127.0.0.1:20000,127.0.0.1:20001,127.0.0.1:20002" }
databases:
{ "_id" : "admin", "partitioned" : false, "primary" : "config" }

对数据库启用分片

1
2
mongos> db.runCommand({"enablesharding":"sharding"})
{ "ok" : 1 }

对数据库下面的表,启用分片–按照’_id’列进行分片

1
2
mongos> db.runCommand({shardcollection: "sharding.testing", key: {_id:1}})
{ "collectionsharded" : "sharding.testing", "ok" : 1 }

配置到这里,集群搭建完毕了!真是不容易啊!!!

配置验证

我们来验证下配置的情况,添加10000条数据到数据库中。

1
2
3
4
5
6
7
D:\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
58
mongos> 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()

唐胡璐 wechat
欢迎您扫一扫上面的微信公众号,订阅我的博客!
分享创造价值,您的支持将鼓励我继续前行!