副本集架构介绍

一个包含3个mongo的复制集架构如下所示:
Mongo
如果主节点失效,会变成:
故障转移
如果加上可选的仲裁节点:
仲裁节点
拥有仲裁节点情况下主服务器失效:
仲裁节点故障转移

环境准备:

单机多实例目录规划

/application/mongo_端口号/为单机多实例存放目录

Server Role
10.0.0.51:28017 PRIMARY
10.0.0.51:28018 SECONDARY
10.0.0.51:28019 SECONDARY
10.0.0.51:28010 ARBITER(可选)

创建多实例目录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[root@db01 ~]# mkdir -p /application/mongo_cluster/mongo_2801{7,8,9}/{conf,logs,pid}
[root@db01 ~]# tree /application/mongo_cluster/mongo_2801*
/application/mongo_cluster/mongo_28017
├── conf
├── logs
└── pid
/application/mongo_cluster/mongo_28018
├── conf
├── logs
└── pid
/application/mongo_cluster/mongo_28019
├── conf
├── logs
└── pid

创建配置文件

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
cat > /application/mongo_cluster/mongo_28017/conf/mongo_28017.conf <<EOF
systemLog:
destination: file
logAppend: true
path: /application/mongo_cluster/mongo_28017/logs/mongodb.log
storage:
journal:
enabled: true
dbPath: /data/mongo_cluster/mongo_28017
directoryPerDB: true
wiredTiger:
engineConfig:
cacheSizeGB: 0.5
directoryForIndexes: true
collectionConfig:
blockCompressor: zlib
indexConfig:
prefixCompression: true
processManagement:
fork: true
pidFilePath: /application/mongo_cluster/mongo_28017/pid/mongod.pid
net:
port: 28017
bindIp: 127.0.0.1,10.0.0.51
replication:
oplogSizeMB: 1024
replSetName: dba58
EOF

------------------
参数介绍:
oplogSizeMB:
#复制操作日志的最大大小(M),该mongod过程基于最大可用空间量创建一个oplog,对于64位系统,oplog通常是可用磁盘的5%,一旦mongod第一次创建了oplog,更改replication.oplogSizeMB将不会影响oplog的大小

replSetName:
#复制集的名称
------------------


#创建另外两个节点的配置文件
cp /application/mongo_cluster/mongo_28017/conf/mongo_28017.conf /application/mongo_cluster/mongo_28018/conf/mongo_28018.conf
cp /application/mongo_cluster/mongo_28017/conf/mongo_28017.conf /application/mongo_cluster/mongo_28019/conf/mongo_28019.conf

#修改端口号
sed -i 's#28017#28018#g' /application/mongo_cluster/mongo_28018/conf/mongo_28018.conf
sed -i 's#28017#28019#g' /application/mongo_cluster/mongo_28019/conf/mongo_28019.conf

创建数据目录

1
2
3
4
5
6
7
[root@db01 ~]# mkdir -p /data/mongo_cluster/mongo_2801{7,8,9}
[root@db01 ~]# tree /data/mongo_cluster/ -L 1
/data/mongo_cluster/
├── mongo_27017
├── mongo_28017
├── mongo_28018
└── mongo_28019

更改目录权限

1
2
3
4
[root@db01 ~]# id mongod
uid=800(mongod) gid=800(mongod) 组=800(mongod)
chown -R mongod:mongod /data/mongo_cluster
chown -R mongod:mongod /application/mongo_cluster

多实例启动测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
mongod -f /application/mongo_cluster/mongo_28017/conf/mongo_28017.conf
mongod -f /application/mongo_cluster/mongo_28018/conf/mongo_28018.conf
mongod -f /application/mongo_cluster/mongo_28019/conf/mongo_28019.conf
---
[root@db01 ~]# ps -ef | grep mongod
root 5291 1 1 12:03 ? 00:00:00 mongod -f /application/mongo_cluster/mongo_28017/conf/mongo_28017.conf
root 5329 1 1 12:03 ? 00:00:00 mongod -f /application/mongo_cluster/mongo_28018/conf/mongo_28018.conf
root 5367 1 1 12:03 ? 00:00:00 mongod -f /application/mongo_cluster/mongo_28019/conf/mongo_28019.conf

[root@db01 ~]# netstat -lntup | grep mongod | wc -l
6
---
mongo db01:28017
mongo db01:28018
mongo db01:28019

配置副本集

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
初始化副本集
mongo db01:28017
> config = {
... _id : "dba58",
... members : [
... {_id : 0, host : " db01:28017"},
... {_id : 1, host : " db01:28018"},
... {_id : 2, host : " db01:28019"},
... ] }
{
"_id" : "dba58",
"members" : [
{
"_id" : 0,
"host" : " db01:28017"
},
{
"_id" : 1,
"host" : " db01:28018"
},
{
"_id" : 2,
"host" : " db01:28019"
}
]
}
> rs.initiate(config)
{
"ok" : 1,
"operationTime" : Timestamp(1590035513, 1),
"$clusterTime" : {
"clusterTime" : Timestamp(1590035513, 1),
"signature" : {
"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"keyId" : NumberLong(0)
}
}
}
dba58:SECONDARY>
dba58:SECONDARY>
dba58:PRIMARY>

---
mongo db01:28018
dba58:SECONDARY>

---
mongo db01:28019
dba58:SECONDARY>

检查副本集状态状态

1
2
3
rs.status();   //查看整体复制集状态 
rs.isMaster(); // 查看当前是否是主节点
rs.conf(); //查看复制集配置信息

写入测试数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
dba58:PRIMARY> db.inventory.insertMany( [
{ "item": "journal", "qty": 25, "size": { "h": 14, "w": 21, "uom": "cm" }, "status": "A" },
{ "item": "notebook", "qty": 50, "size": { "h": 8.5, "w": 11, "uom": "in" }, "status": "A" },
{ "item": "paper", "qty": 100, "size": { "h": 8.5, "w": 11, "uom": "in" }, "status": "D" },
{ "item": "planner", "qty": 75, "size": { "h": 22.85, "w": 30, "uom": "cm" }, "status": "D" },
{ "item": "postcard", "qty": 45, "size": { "h": 10, "w": 15.25, "uom": "cm" }, "status": "A" }
]);
dba58:PRIMARY> db.inventory.find()

//从节点查看
dba58:SECONDARY> db.inventory.find()
...
"errmsg" : "not master and slaveOk=false",
...

默认从节点不可直接查询:
临时解决
dba58:SECONDARY> rs.slaveOk();
dba58:SECONDARY> db.inventory.find()
{ "_id" : ObjectId("5ec60b6a9df565bf8d6b6bcc"), "item" : "postcard", "qty" : 45, "size" : { "h" : 10, "w" : 15.25, "uom" : "cm" }, "status" : "A" }

永久解决
[root@db01 ~]# echo "rs.slaveOk();" >> .mongorc.js

故障转移

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
[root@db01 ~]#  mongod -f /application/mongo_cluster/mongo_28017/conf/mongo_28017.conf --shutdown
killing process with pid: 5291

1.登陆原副节点查看:
[root@db01 ~]# mongo db01:28018
dba58:PRIMARY> rs.isMaster();
{
"hosts" : [
"db01:28017",
"db01:28018",
"db01:28019"
],
"setName" : "dba58",
"setVersion" : 1,
"ismaster" : true,
"secondary" : false,
"primary" : "db01:28018",
"me" : "db01:28018", //从节点转移致主节点

2.尝试修改数据:
dba58:PRIMARY> db.test.insert({"name":"zhangya","age":27,"ad":"北京市朝阳区"})
WriteResult({ "nInserted" : 1 })
dba58:PRIMARY> db.test.find()
{ "_id" : ObjectId("5ec6120d946241e339cfb2d0"), "name" : "zhangya", "age" : 27, "ad" : "北京市朝阳区" }

3.在从库上查看:
[root@db01 ~]# mongo db01:28019
dba58:SECONDARY> db.test.find()
{ "_id" : ObjectId("5ec6120d946241e339cfb2d0"), "name" : "zhangya", "age" : 27, "ad" : "北京市朝阳区" }

4.重新启动损坏节点:
[root@db01 ~]# mongod -f /application/mongo_cluster/mongo_28017/conf/mongo_28017.conf
[root@db01 ~]# mongo db01:28017
dba58:SECONDARY>

副本集的权重调整和主库降级

检查当前配置

1
2
3
4
5
6
7
8
9
10
11
12
13
dba58:SECONDARY> rs.conf();
"_id" : 0,
"host" : "db01:28017",
"priority" : 1,

"_id" : 1,
"host" : "db01:28018",
"priority" : 1,

"_id" : 2,
"host" : "db01:28019",
"priority" : 1,
//现在三个成员权限都为1

在主库中执行如下

1
2
3
4
config = rs.conf() #读取当前配置
config.members[2].priority=100 #修改指定节点权重为100,此处我修改了 节点2即10.0.0.51:28019
rs.reconfig(config) #使生效
rs.stepDown() #主节点主动降价,重新选举

检查集群状态

1
2
3
4
5
6
7
8
9
10
11
12
13
dba58:SECONDARY> rs.isMaster();
{
"hosts" : [
"db01:28017",
"db01:28018",
"db01:28019"
],
"setName" : "dba58",
"setVersion" : 2,
"ismaster" : false,
"secondary" : true,
"primary" : "db01:28019", //28019成功晋升
"me" : "db01:28018",

恢复权重

1
2
3
4
5
[root@db01 ~]# mongo db01:28019 //进入主节点
dba58:PRIMARY>
config = rs.conf()
config.members[2].priority=1
rs.reconfig(config)

检查节点2权重

1
2
3
4
dba58:PRIMARY> rs.conf()
"_id" : 2,
"host" : "db01:28019",
"priority" : 1,

扩容收缩和仲裁节点

扩容,添加节点

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
#创建新节点目录及启动
mkdir /application/mongo_cluster/mongo_28010/{conf,logs,pid} -p
mkdir /data/mongo_cluster/mongo_28010

#配置新节点
cp /application/mongo_cluster/mongo_28017/conf/mongo_28017.conf /application/mongo_cluster/mongo_28010/conf/mongo_28010.conf
sed -i 's#28017#28010#g' /application/mongo_cluster/mongo_28010/conf/mongo_28010.conf
mongod -f /application/mongo_cluster/mongo_28010/conf/mongo_28010.conf

#启动
mongo db01:28010
>
>

#增加节点,进入主节点
[root@db01 ~]# mongo db01:28019
dba58:PRIMARY> use admin
switched to db admin
dba58:PRIMARY> rs.add("db01:28010") //添加新节点到集群

#检查集群配置信息
[root@db01 ~]# mongo db01:28010
dba58:SECONDARY>
dba58:SECONDARY> rs.conf()
"_id" : 0,
"host" : "db01:28017",
"priority" : 1,

"_id" : 1,
"host" : "db01:28018",
"priority" : 1,

"_id" : 2,
"host" : "db01:28019",
"priority" : 1,

"_id" : 3, <==
"host" : "db01:28010",
"priority" : 1,
dba58:SECONDARY> rs.isMaster();
"hosts" : [
"db01:28017",
"db01:28018",
"db01:28019",
"db01:28010"
],
"setName" : "dba58",
"primary" : "db01:28019",
"me" : "db01:28010",

缩容,删除节点

1
2
3
4
5
6
7
8
9
10
#主节点操作
[root@db01 ~]# mongo db01:28019
dba58:PRIMARY> rs.remove("db01:28010")

#此时从节点变成了OTHER状态
[root@db01 ~]# mongo db01:28010
dba58:OTHER>

#现在可以关闭节点了
[mongo@db01 ~]$ mongod -f /application/mongo_cluster/mongo_28010/conf/mongo_28010.conf --shutdown

增加仲裁节点

官方地址:https://docs.mongodb.com/manual/tutorial/add-replica-set-arbiter/
Arbiter 节点只参与投票,不能被选为 Primary,并且不跟 Primary 同步数据。

环境恢复

1
2
3
4
5
6
7
8
#清空 28010 节点的数据
\rm -rf /data/mongo_cluster/mongo_28010/*

#启动节点
mongod -f /application/mongo_cluster/mongo_28010/conf/mongo_28010.conf

#检查
[root@db01 ~]# mongo db01:28010

添加仲裁节点

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
[root@db01 ~]# mongo db01:28019
dba58:PRIMARY> rs.addArb("db01:28010")

#检查集群状态:
dba58:PRIMARY> rs.status()
"_id" : 3,
"name" : "db01:28010",
"health" : 1,
"state" : 7,
"stateStr" : "ARBITER", <==

#检查仲裁节点
[root@db01 ~]# mongo db01:28010
dba58:ARBITER>

#删除仲裁节点
[root@db01 ~]# mongo db01:28019
dba58:PRIMARY> rs.remove("db01:28010")

[root@db01 ~]# mongo db01:28010
dba58:OTHER>