mongodb的Replica Set主从配置

mongodb的Replica Set主从配置

配置

mongodb有两种主从配置,一种是master/slave模式,另一种是Replica Set模式。由于Replica Set有故障自动切换功能,而master/slave没有,所以master/slave已经不被推荐使用。

启动三个数据库,先准备三套文件夹用来存放数据库文件。然后是启动命令。其中,--replSet参数指定Replica Set的名字,任意,最好有意义。

1
2
3
4
5
mongod --maxConns=100 --port=27017 --bind_ip=127.0.0.1 --dbpath=/home/cellargalaxy/file/mongodb/db --logpath=/home/cellargalaxy/file/mongodb/log/mongodb.log --replSet rs0

mongod --maxConns=100 --port=27018 --bind_ip=127.0.0.1 --dbpath=/home/cellargalaxy/file/mongodb/db2 --logpath=/home/cellargalaxy/file/mongodb/log2/mongodb.log --replSet rs0

mongod --maxConns=100 --port=27019 --bind_ip=127.0.0.1 --dbpath=/home/cellargalaxy/file/mongodb/db3 --logpath=/home/cellargalaxy/file/mongodb/log3/mongodb.log --replSet rs0

然后用mongo --host 127.0.0.1 --port 27017登录27017。

1
2
3
4
5
6
7
8
//初始化
rs.initiate()
//添加数据库
rs.add("127.0.0.1:27017")
rs.add("127.0.0.1:27018")
rs.add("127.0.0.1:27019")
//查看各个数据库的状态
rs.status()

添加完后,这三个数据库会自己进行选举,决定谁是主数据库,谁是从数据库,效果:

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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
> rs.initiate()//初始化
{
"info2" : "no configuration specified. Using a default configuration for the set",
"me" : "127.0.0.1:27017",
"ok" : 1,
"operationTime" : Timestamp(1526472651, 1),
"$clusterTime" : {
"clusterTime" : Timestamp(1526472651, 1),
"signature" : {
"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"keyId" : NumberLong(0)
}
}
}
rs0:SECONDARY> //可以看到一开始他自己是从数据库(SECONDARY)
rs0:PRIMARY> //回车之后选举完成,自己就变成了主数据库(PRIMARY)
rs0:PRIMARY> rs.add("127.0.0.1:27017")//添加数据库
{
"ok" : 0,
"errmsg" : "Found two member configurations with same host field, members.0.host == members.1.host == 127.0.0.1:27017",
"code" : 103,
"codeName" : "NewReplicaSetConfigurationIncompatible",
"operationTime" : Timestamp(1526472673, 1),
"$clusterTime" : {
"clusterTime" : Timestamp(1526472673, 1),
"signature" : {
"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"keyId" : NumberLong(0)
}
}
}
rs0:PRIMARY> rs.add("127.0.0.1:27018")
{
"ok" : 1,
"operationTime" : Timestamp(1526472678, 1),
"$clusterTime" : {
"clusterTime" : Timestamp(1526472678, 1),
"signature" : {
"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"keyId" : NumberLong(0)
}
}
}
rs0:PRIMARY> rs.add("127.0.0.1:27019")
{
"ok" : 1,
"operationTime" : Timestamp(1526472680, 1),
"$clusterTime" : {
"clusterTime" : Timestamp(1526472680, 1),
"signature" : {
"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"keyId" : NumberLong(0)
}
}
}
rs0:PRIMARY> rs.status()//查看各个数据库的状态
{
"set" : "rs0",//Replica Set的名字
"date" : ISODate("2018-05-16T12:11:28.944Z"),
"myState" : 1,
"term" : NumberLong(1),
"heartbeatIntervalMillis" : NumberLong(2000),
"optimes" : {
"lastCommittedOpTime" : {
"ts" : Timestamp(1526472680, 1),
"t" : NumberLong(1)
},
"readConcernMajorityOpTime" : {
"ts" : Timestamp(1526472680, 1),
"t" : NumberLong(1)
},
"appliedOpTime" : {
"ts" : Timestamp(1526472680, 1),
"t" : NumberLong(1)
},
"durableOpTime" : {
"ts" : Timestamp(1526472680, 1),
"t" : NumberLong(1)
}
},
"members" : [
{
"_id" : 0,
"name" : "127.0.0.1:27017",//数据库地址
"health" : 1,
"state" : 1,
"stateStr" : "PRIMARY",//主数据库
"uptime" : 103,
"optime" : {
"ts" : Timestamp(1526472680, 1),
"t" : NumberLong(1)
},
"optimeDate" : ISODate("2018-05-16T12:11:20Z"),
"infoMessage" : "could not find member to sync from",
"electionTime" : Timestamp(1526472651, 2),
"electionDate" : ISODate("2018-05-16T12:10:51Z"),
"configVersion" : 3,
"self" : true
},
{
"_id" : 1,
"name" : "127.0.0.1:27018",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 10,
"optime" : {
"ts" : Timestamp(1526472680, 1),
"t" : NumberLong(1)
},
"optimeDurable" : {
"ts" : Timestamp(1526472680, 1),
"t" : NumberLong(1)
},
"optimeDate" : ISODate("2018-05-16T12:11:20Z"),
"optimeDurableDate" : ISODate("2018-05-16T12:11:20Z"),
"lastHeartbeat" : ISODate("2018-05-16T12:11:28.385Z"),
"lastHeartbeatRecv" : ISODate("2018-05-16T12:11:27.388Z"),
"pingMs" : NumberLong(0),
"syncingTo" : "127.0.0.1:27019",
"configVersion" : 3
},
{
"_id" : 2,
"name" : "127.0.0.1:27019",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 8,
"optime" : {
"ts" : Timestamp(1526472680, 1),
"t" : NumberLong(1)
},
"optimeDurable" : {
"ts" : Timestamp(1526472680, 1),
"t" : NumberLong(1)
},
"optimeDate" : ISODate("2018-05-16T12:11:20Z"),
"optimeDurableDate" : ISODate("2018-05-16T12:11:20Z"),
"lastHeartbeat" : ISODate("2018-05-16T12:11:28.386Z"),
"lastHeartbeatRecv" : ISODate("2018-05-16T12:11:28.898Z"),
"pingMs" : NumberLong(0),
"syncingTo" : "127.0.0.1:27017",
"configVersion" : 3
}
],
"ok" : 1,
"operationTime" : Timestamp(1526472680, 1),
"$clusterTime" : {
"clusterTime" : Timestamp(1526472680, 1),
"signature" : {
"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"keyId" : NumberLong(0)
}
}
}

测试

  1. 先连上27018,从数据库要对主数据库读取,还需要到从数据库进行设置。

    1
    rs.slaveOk()

  2. 回到27017插入数据。跟mysql一样,只有主数据库才能写,全部数据库都能读

    1
    2
    3
    4
    5
    6
    rs0:PRIMARY> use mycloud
    switched to db mycloud
    rs0:PRIMARY> db.mycloud.insert({name:'name1',age:11})
    WriteResult({ "nInserted" : 1 })
    rs0:PRIMARY> db.mycloud.find()
    { "_id" : ObjectId("5afc24bc37f9ecd1e677ee57"), "name" : "name1", "age" : 11 }

  3. 又回到27018,看看数据同步了没

    1
    2
    3
    4
    rs0:SECONDARY> use mycloud
    switched to db mycloud
    rs0:SECONDARY> db.mycloud.find()
    { "_id" : ObjectId("5afc24bc37f9ecd1e677ee57"), "name" : "name1", "age" : 11 }

  4. 再测试一下27019,先不rs.slaveOk()

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    rs0:SECONDARY> use mycloud
    switched to db mycloud
    rs0:SECONDARY> db.mycloud.find()
    Error: error: {
    "operationTime" : Timestamp(1526474043, 1),
    "ok" : 0,
    "errmsg" : "not master and slaveOk=false",
    "code" : 13435,
    "codeName" : "NotMasterNoSlaveOk",
    "$clusterTime" : {
    "clusterTime" : Timestamp(1526474043, 1),
    "signature" : {
    "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
    "keyId" : NumberLong(0)
    }
    }
    }

  5. 对27019执行rs.slaveOk()

    1
    2
    3
    4
    rs0:SECONDARY> rs.slaveOk()
    switched to db mycloud
    rs0:SECONDARY> db.mycloud.find()
    { "_id" : ObjectId("5afc24bc37f9ecd1e677ee57"), "name" : "name1", "age" : 11 }

故障自动切换

故障自动切换是Replica Set才有,master/slave没有的功能。故障自动切换就是当主数据库挂了,其他从数据库会自行进行选举,选择出新的主数据库。如果停掉主数据库,等一会,在其他从数据库里回车或者用rs.status()就能查看到主数据库切换了。

不足

现在数据库是不设防,不需要密码登录的。目前还没找到密码登录的主从同步的方法。

参考文章:
mongodb 副本集(Replica Set)搭建

MongoDB Replication Set 的配置

[MongoDB] 安装MongoDB配置Replica Set

学习MongoDB(二) Replica Set集群配置


mongodb的Replica Set主从配置
https://cellargalaxy.github.io/posts/折腾/03.mongodb的Replica Set主从配置/
作者
cellargalaxy
发布于
2018年5月15日
许可协议