MongoDB基础请参考:http://blog.51cto.com/kaliarch/2044423
MongoDB(replica set)请参考:http://blog.51cto.com/kaliarch/2044618
一、概述
1.1 背景
为解决mongodb在replica set每个从节点上面的数据库均是对数据库的全量拷贝,从节点压力在高并发大数据量的场景下存在很大挑战,同时考虑到后期mongodb集群的在数据压力巨大时的扩展性,应对海量数据引出了分片机制。
1.2 分片概念
分片是将数据库进行拆分,将其分散在不同的机器上的过程,无需功能强大的服务器就可以存储更多的数据,处理更大的负载,在总数据中,将集合切成小块,将这些块分散到若干片中,每个片只负载总数据的一部分,通过一个知道数据与片对应关系的组件mongos的路由进程进行操作。
1.3 基础组件
其利用到了四个组件:mongos,config server,shard,replica set
mongos:数据库集群请求的入口,所有请求需要经过mongos进行协调,无需在应用层面利用程序来进行路由选择,mongos其自身是一个请求分发中心,负责将外部的请求分发到对应的shard服务器上,mongos作为统一的请求入口,为防止mongos单节点故障,一般需要对其做HA。
config server:配置服务器,存储所有数据库元数据(分片,路由)的配置。mongos本身没有物理存储分片服务器和数据路由信息,只是存缓存在内存中来读取数据,mongos在第一次启动或后期重启时候,就会从config server中加载配置信息,如果配置服务器信息发生更新会通知所有的mongos来更新自己的状态,从而保证准确的请求路由,生产环境中通常也需要多个config server,防止配置文件存在单节点丢失问题。
shard:在传统意义上来讲,如果存在海量数据,单台服务器存储1T压力非常大,无论考虑数据库的硬盘,网络IO,又有CPU,内存的瓶颈,如果多台进行分摊1T的数据,到每台上就是可估量的较小数据,在mongodb集群只要设置好分片规则,通过mongos操作数据库,就可以自动把对应的操作请求转发到对应的后端分片服务器上。
replica set:在总体mongodb集群架构中,对应的分片节点,如果单台机器下线,对应整个集群的数据就会出现部分缺失,这是不能发生的,因此对于shard节点需要replica set来保证数据的可靠性,生产环境通常为2个副本+1个仲裁。
1.4 架构图
二、安装部署
2.1 基础环境
为了节省服务器,采用多实例配置,三个mongos,三个config server,单个服务器上面运行不通角色的shard(为了后期数据分片均匀,将三台shard在各个服务器上充当不同的角色。),在一个节点内采用replica set保证高可用,对应主机与端口信息如下:
主机名 |
IP地址 |
组件mongos |
组件config server |
shard |
mongodb-1 |
172.20.6.10 |
端口:20000 |
端口:21000 |
主节点: 22001 |
副本节点:22002 |
||||
仲裁节点:22003 |
||||
mongodb-2 |
172.20.6.11 |
端口:20000 |
端口:21000 |
仲裁节点:22001 |
主节点: 22002 |
||||
副本节点:22003 |
||||
mongodb-3 |
172.20.6.12 |
端口:20000 |
端口:21000 |
副本节点:22001 |
仲裁节点:22002 |
||||
主节点: 22003 |
2.2、安装部署
2.2.1 软件下载目录创建
1
2
3
4
5
|
wget -c https:
//fastdl
.mongodb.org
/linux/mongodb-linux-x86_64-rhel62-3
.4.10.tgz
tar
-zxvf mongodb-linux-x86_64-rhel62-3.4.10.tgz
ln
-sv mongodb-linux-x86_64-rhel62-3.4.10 mongodb
echo
"PATH=$PAHT:/usr/local/mongodb/bin"
>
/etc/profile
.d
/mongodb
.sh
source
/etc/profile
.d
/mongodb
.sh
|
2.2.2 创建目录
分别在mongodb-1/mongodb-2/mongodb-3创建目录及日志文件
1
2
3
4
5
6
7
8
9
10
|
mkdir
-p
/data/mongodb/mongos/
{log,conf}
mkdir
-p
/data/mongodb/mongoconf/
{data,log,conf}
mkdir
-p
/data/mongodb/shard1/
{data,log,conf}
mkdir
-p
/data/mongodb/shard2/
{data,log,conf}
mkdir
-p
/data/mongodb/shard3/
{data,log,conf}
touch
/data/mongodb/mongos/log/mongos
.log
touch
/data/mongodb/mongoconf/log/mongoconf
.log
touch
/data/mongodb/shard1/log/shard1
.log
touch
/data/mongodb/shard2/log/shard2
.log
touch
/data/mongodb/shard3/log/shard3
.log
|
2.2.3 配置config server副本集
在mongodb3.4版本后要求配置服务器也创建为副本集,在此副本集名称:replconf
在三台服务器上配置config server副本集配置文件,并启动服务
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
cat
>
/data/mongodb/mongoconf/conf/mongoconf
.conf<<EOFdbpath=
/data/mongodb/mongoconf/data
logpath=
/data/mongodb/mongoconf/log/mongoconf
.log
#定义config server日志文件
logappend=
true
port = 21000
maxConns = 1000
#链接数
journal =
true
#日志开启
journalCommitInterval = 200
fork =
true
#后台执行
syncdelay = 60
oplogSize = 1000
configsvr =
true
#配置服务器
replSet=replconf
#config server配置集replconf
EOF
mongod -f
/data/mongodb/mongoconf/conf/mongoconf
.conf
#三台服务器均启动config server
|
任意登录一台服务器进行配置服务器副本集初始化
1
2
3
4
5
6
7
|
use admin
config = {_id:
"replconf"
,members:[
{_id:0,host:
"172.20.6.10:21000"
},
{_id:1,host:
"172.20.6.11:21000"
},
{_id:2,host:
"172.20.6.12:21000"
},]
}
rs.initiate(config);
|
查看集群状态:
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
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
|
replconf:OTHER> rs.status()
{
"set"
:
"replconf"
,
"date"
: ISODate(
"2017-12-04T07:42:09.054Z"
),
"myState"
: 1,
"term"
: NumberLong(1),
"configsvr"
:
true
,
"heartbeatIntervalMillis"
: NumberLong(2000),
"optimes"
: {
"lastCommittedOpTime"
: {
"ts"
: Timestamp(1512373328, 1),
"t"
: NumberLong(1)
},
"readConcernMajorityOpTime"
: {
"ts"
: Timestamp(1512373328, 1),
"t"
: NumberLong(1)
},
"appliedOpTime"
: {
"ts"
: Timestamp(1512373328, 1),
"t"
: NumberLong(1)
},
"durableOpTime"
: {
"ts"
: Timestamp(1512373328, 1),
"t"
: NumberLong(1)
}
},
"members"
: [
{
"_id"
: 0,
"name"
:
"172.20.6.10:21000"
,
"health"
: 1,
"state"
: 1,
"stateStr"
:
"PRIMARY"
,
"uptime"
: 221,
"optime"
: {
"ts"
: Timestamp(1512373328, 1),
"t"
: NumberLong(1)
},
"optimeDate"
: ISODate(
"2017-12-04T07:42:08Z"
),
"infoMessage"
:
"could not find member to sync from"
,
"electionTime"
: Timestamp(1512373296, 1),
"electionDate"
: ISODate(
"2017-12-04T07:41:36Z"
),
"configVersion"
: 1,
"self"
:
true
},
{
"_id"
: 1,
"name"
:
"172.20.6.11:21000"
,
"health"
: 1,
"state"
: 2,
"stateStr"
:
"SECONDARY"
,
"uptime"
: 42,
"optime"
: {
"ts"
: Timestamp(1512373318, 1),
"t"
: NumberLong(1)
},
"optimeDurable"
: {
"ts"
: Timestamp(1512373318, 1),
"t"
: NumberLong(1)
},
"optimeDate"
: ISODate(
"2017-12-04T07:41:58Z"
),
"optimeDurableDate"
: ISODate(
"2017-12-04T07:41:58Z"
),
"lastHeartbeat"
: ISODate(
"2017-12-04T07:42:08.637Z"
),
"lastHeartbeatRecv"
: ISODate(
"2017-12-04T07:42:07.648Z"
),
"pingMs"
: NumberLong(0),
"syncingTo"
:
"172.20.6.10:21000"
,
"configVersion"
: 1
},
{
"_id"
: 2,
"name"
:
"172.20.6.12:21000"
,
"health"
: 1,
"state"
: 2,
"stateStr"
:
"SECONDARY"
,
"uptime"
: 42,
"optime"
: {
"ts"
: Timestamp(1512373318, 1),
"t"
: NumberLong(1)
},
"optimeDurable"
: {
"ts"
: Timestamp(1512373318, 1),
"t"
: NumberLong(1)
},
"optimeDate"
: ISODate(
"2017-12-04T07:41:58Z"
),
"optimeDurableDate"
: ISODate(
"2017-12-04T07:41:58Z"
),
"lastHeartbeat"
: ISODate(
"2017-12-04T07:42:08.637Z"
),
"lastHeartbeatRecv"
: ISODate(
"2017-12-04T07:42:07.642Z"
),
"pingMs"
: NumberLong(0),
"syncingTo"
:
"172.20.6.10:21000"
,
"configVersion"
: 1
}
],
"ok"
: 1
}
|
此时config server集群已经配置完成,mongodb-1为primary,mongdb-2/mongodb-3为secondary
2.2.4 配置shard集群
三台服务器均进行shard集群配置
shard1配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
cat
>
/data/mongodb/shard1/conf/shard
.conf <<EOF
dbpath=
/data/mongodb/shard1/data
logpath =
/data/mongodb/shard1/log/shard1
.log
port = 22001
logappend =
true
nohttpinterface =
true
fork =
true
oplogSize = 4096
journal =
true
#engine = wiredTiger
#cacheSizeGB = 38G
smallfiles=
true
shardsvr=
true
#shard服务器
replSet=shard1
#副本集名称shard1
EOF
mongod -f
/data/mongodb/shard1/conf/shard
.conf
#启动shard服务
|
查看此时服务已经正常启动,shard1的22001端口已经正常监听,接下来登录mongodb-1服务器进行shard1副本集初始化
1
2
3
4
5
6
7
8
|
mongo 172.20.6.10:22001
use admin
config = {_id:
"shard1"
,members:[
{_id:0,host:
"172.20.6.10:22001"
},
{_id:1,host:
"172.20.6.11:22001"
,arbiterOnly:
true
},
{_id:2,host:
"172.20.6.12:22001"
},]
}
rs.initiate(config);
|
查看集群状态,只列出了部分信息:
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
|
{
"_id"
: 0,
"name"
:
"172.20.6.10:22001"
,
"health"
: 1,
"state"
: 1,
"stateStr"
:
"PRIMARY"
,
#mongodb-1为primary
"uptime"
: 276,
"optime"
: {
"ts"
: Timestamp(1512373911, 1),
"t"
: NumberLong(1)
},
"optimeDate"
: ISODate(
"2017-12-04T07:51:51Z"
),
"infoMessage"
:
"could not find member to sync from"
,
"electionTime"
: Timestamp(1512373879, 1),
"electionDate"
: ISODate(
"2017-12-04T07:51:19Z"
),
"configVersion"
: 1,
"self"
:
true
},
{
"_id"
: 1,
"name"
:
"172.20.6.11:22001"
,
"health"
: 1,
"state"
: 7,
"stateStr"
:
"ARBITER"
,
#mongodb-2为arbiter
"uptime"
: 45,
"lastHeartbeat"
: ISODate(
"2017-12-04T07:51:53.597Z"
),
"lastHeartbeatRecv"
: ISODate(
"2017-12-04T07:51:51.243Z"
),
"pingMs"
: NumberLong(0),
"configVersion"
: 1
},
{
"_id"
: 2,
"name"
:
"172.20.6.12:22001"
,
"health"
: 1,
"state"
: 2,
"stateStr"
:
"SECONDARY"
,
#mongodb-3为secondary
"uptime"
: 45,
"optime"
: {
"ts"
: Timestamp(1512373911, 1),
"t"
: NumberLong(1)
},
|
此时shard1 副本集已经配置完成,mongodb-1为primary,mongodb-2为arbiter,mongodb-3为secondary。
同样的操作进行shard2配置和shard3配置
注意:进行shard2的副本集初始化,在mongodb-2, 初始化shard3副本集在mongodb-3上进行操作。
shard2配置文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
cat
>
/data/mongodb/shard2/conf/shard
.conf <<EOF
dbpath=
/data/mongodb/shard2/data
logpath =
/data/mongodb/shard2/log/shard2
.log
port = 22002
logappend =
true
nohttpinterface =
true
fork =
true
oplogSize = 4096
journal =
true
#engine = wiredTiger
#cacheSizeGB = 38G
smallfiles=
true
shardsvr=
true
replSet=shard2
EOF
mongod -f
/data/mongodb/shard2/conf/shard
.conf
|
shard3配置文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
cat
>
/data/mongodb/shard3/conf/shard
.conf <<EOF
dbpath=
/data/mongodb/shard3/data
logpath =
/data/mongodb/shard3/log/shard3
.log
port = 22003
logappend =
true
nohttpinterface =
true
fork =
true
oplogSize = 4096
journal =
true
#engine = wiredTiger
#cacheSizeGB = 38G
smallfiles=
true
shardsvr=
true
replSet=shard3
EOF
mongod -f
/data/mongodb/shard2/conf/shard
.conf
|
在mongodb-2上进行shard2副本集初始化
1
2
3
4
5
6
7
8
9
|
mongo 172.20.6.11:22002
#登录mongodb-2
use admin
config = {_id:
"shard2"
,members:[
{_id:0,host:
"172.20.6.10:22002"
},
{_id:1,host:
"172.20.6.11:22002"
},
{_id:2,host:
"172.20.6.12:22002"
,arbiterOnly:
true
},]
}
rs.initiate(config);
|
查看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
|
{
"_id"
: 0,
"name"
:
"172.20.6.10:22002"
,
"health"
: 1,
"state"
: 2,
"stateStr"
:
"SECONDARY"
,
#mongodb-2为secondary
"uptime"
: 15,
"optime"
: {
"ts"
: Timestamp(1512374668, 1),
"t"
: NumberLong(1)
},
"optimeDurable"
: {
"ts"
: Timestamp(1512374668, 1),
"t"
: NumberLong(1)
},
"optimeDate"
: ISODate(
"2017-12-04T08:04:28Z"
),
"optimeDurableDate"
: ISODate(
"2017-12-04T08:04:28Z"
),
"lastHeartbeat"
: ISODate(
"2017-12-04T08:04:30.527Z"
),
"lastHeartbeatRecv"
: ISODate(
"2017-12-04T08:04:28.492Z"
),
"pingMs"
: NumberLong(0),
"syncingTo"
:
"172.20.6.11:22002"
,
"configVersion"
: 1
},
{
"_id"
: 1,
"name"
:
"172.20.6.11:22002"
,
"health"
: 1,
"state"
: 1,
"stateStr"
:
"PRIMARY"
,
#mongodb-2为primary
"uptime"
: 211,
"optime"
: {
"ts"
: Timestamp(1512374668, 1),
"t"
: NumberLong(1)
},
"optimeDate"
: ISODate(
"2017-12-04T08:04:28Z"
),
"infoMessage"
:
"could not find member to sync from"
,
"electionTime"
: Timestamp(1512374666, 1),
"electionDate"
: ISODate(
"2017-12-04T08:04:26Z"
),
"configVersion"
: 1,
"self"
:
true
},
{
"_id"
: 2,
"name"
:
"172.20.6.12:22002"
,
#mongodb-3为arbiter
"health"
: 1,
"state"
: 7,
"stateStr"
:
"ARBITER"
,
"uptime"
: 15,
"lastHeartbeat"
: ISODate(
"2017-12-04T08:04:30.527Z"
),
"lastHeartbeatRecv"
: ISODate(
"2017-12-04T08:04:28.384Z"
),
"pingMs"
: NumberLong(0),
"configVersion"
: 1
}
|
登录mongodb-3进行shard3副本集初始化
1
2
3
4
5
6
7
8
9
|
mongo 172.20.6.12:22003
#登录mongodb-3
use admin
config = {_id:
"shard3"
,members:[
{_id:0,host:
"172.20.6.10:22003"
,arbiterOnly:
true
},
{_id:1,host:
"172.20.6.11:22003"
},
{_id:2,host:
"172.20.6.12:22003"
},]
}
rs.initiate(config);
|
查看shard3副本集状态
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
|
{
"_id"
: 0,
"name"
:
"172.20.6.10:22003"
,
"health"
: 1,
"state"
: 7,
"stateStr"
:
"ARBITER"
,
#mongodb-1为arbiter
"uptime"
: 18,
"lastHeartbeat"
: ISODate(
"2017-12-04T08:07:37.488Z"
),
"lastHeartbeatRecv"
: ISODate(
"2017-12-04T08:07:36.224Z"
),
"pingMs"
: NumberLong(0),
"configVersion"
: 1
},
{
"_id"
: 1,
"name"
:
"172.20.6.11:22003"
,
"health"
: 1,
"state"
: 2,
"stateStr"
:
"SECONDARY"
,
#mongodb-2为secondary
"uptime"
: 18,
"optime"
: {
"ts"
: Timestamp(1512374851, 1),
"t"
: NumberLong(1)
},
"optimeDurable"
: {
"ts"
: Timestamp(1512374851, 1),
"t"
: NumberLong(1)
},
"optimeDate"
: ISODate(
"2017-12-04T08:07:31Z"
),
"optimeDurableDate"
: ISODate(
"2017-12-04T08:07:31Z"
),
"lastHeartbeat"
: ISODate(
"2017-12-04T08:07:37.488Z"
),
"lastHeartbeatRecv"
: ISODate(
"2017-12-04T08:07:36.297Z"
),
"pingMs"
: NumberLong(0),
"syncingTo"
:
"172.20.6.12:22003"
,
"configVersion"
: 1
},
{
"_id"
: 2,
"name"
:
"172.20.6.12:22003"
,
"health"
: 1,
"state"
: 1,
"stateStr"
:
"PRIMARY"
,
#mongodb-3为primary
"uptime"
: 380,
"optime"
: {
"ts"
: Timestamp(1512374851, 1),
"t"
: NumberLong(1)
},
"optimeDate"
: ISODate(
"2017-12-04T08:07:31Z"
),
"infoMessage"
:
"could not find member to sync from"
,
"electionTime"
: Timestamp(1512374849, 1),
"electionDate"
: ISODate(
"2017-12-04T08:07:29Z"
),
"configVersion"
: 1,
"self"
:
true
}
|
此时shard集群全部已经配置完毕。
2.2.5 配置路由服务器mongos
目前三台服务器的配置服务器和分片服务器均已启动,配置三台mongos服务器
由于mongos服务器的配置是从内存中加载,所以自己没有存在数据目录configdb连接为配置服务器集群
1
2
3
4
5
6
7
8
9
10
|
cat
>
/data/mongodb/mongos/conf/mongos
.conf<<EOF
--logpath=
/data/mongodb/mongos/log/mongos
.log
logappend=
true
port = 20000
maxConns = 1000
configdb=replconf
/172
.20.6.10:21000,172.20.6.11:21000,172.20.6.12:21000
#制定config server集群
fork =
true
EOF
mongos -f
/data/mongodb/mongos/conf/mongos
.conf
#启动mongos服务
|
目前config server集群/shard集群/mongos服务均已启动,但此时为设置分片,还不能使用分片功能。需要登录mongos启用分片
登录任意一台mongos
1
2
3
4
5
|
mongo 172.20.6.10:20000
use admin
db.runCommand({addshard:
"shard1/172.20.6.10:22001,172.20.6.11:22001,172.20.6.12:22001"
})
db.runCommand({addshard:
"shard2/172.20.6.10:22002,172.20.6.11:22002,172.20.6.12:22002"
})
db.runCommand({addshard:
"shard3/172.20.6.10:22003,172.20.6.11:22003,172.20.6.12:22003"
})
|
查看集群
三、 测试
目前配置服务、路由服务、分片服务、副本集服务都已经串联起来了,此时进行数据插入,数据能够自动分片。连接在mongos上让指定的数据库、指定的集合分片生效。
注意:设置分片需要在admin数据库进行
1
2
3
|
use admin
db.runCommand( { enablesharding :
"kaliarchdb"
});
#开启kaliarch库分片功能
db.runCommand( { shardcollection :
"kaliarchdb.table1"
,key : {_id:
"hashed"
} } )
#指定数据库里需要分片的集合tables和片键_id
|
设置kaliarchdb的 table1 表需要分片,根据 _id 自动分片到 shard1 ,shard2,shard3 上面去。
查看分片信息
测试插入数据
1
2
|
use kaliarchdb;
for
(var i = 1; i <= 100000; i++) db.table1.save({_id:i,
"test1"
:
"testval1"
});
|
查看分片情况:(省去部分信息)
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
|
db.table1.stats()
{
"sharded"
:
true
,
"capped"
:
false
,
"ns"
:
"kaliarchdb.table1"
,
"count"
: 100000,
#总count
"size"
: 3800000,
"storageSize"
: 1335296,
"totalIndexSize"
: 4329472,
"indexSizes"
: {
"_id_"
: 1327104,
"_id_hashed"
: 3002368
},
"avgObjSize"
: 38,
"nindexes"
: 2,
"nchunks"
: 6,
"shards"
: {
"shard1"
: {
"ns"
:
"kaliarchdb.table1"
,
"size"
: 1282690,
"count"
: 33755,
#shard1的count数
"avgObjSize"
: 38,
"storageSize"
: 450560,
"capped"
:
false
,
......
"shard2"
: {
"ns"
:
"kaliarchdb.table1"
,
"size"
: 1259434,
"count"
: 33143,
#shard2的count数
"avgObjSize"
: 38,
"storageSize"
: 442368,
"capped"
:
false
,
.......
"shard3"
: {
"ns"
:
"kaliarchdb.table1"
,
"size"
: 1257876,
"count"
: 33102,
#shard3的count数
"avgObjSize"
: 38,
"storageSize"
: 442368,
"capped"
:
false
,
|
此时架构中的mongos,config server,shard集群均已经搭建部署完毕,在实际生成环境话需要对前端的mongos做高可用来提示整体高可用。