How Mongodb Build The Replica Set

Server environment

1
2
3
4
5
$ cat /etc/issue
Ubuntu 14.04.5 LTS

$ mongod -version
db version v3.0.15

Replica set

Replication is a process of synchronizing data across multiple servers.

  • mongodb support replica set and master-slave copy, master-slave copy of the official is no longer recommended (does not support automatic failover)

Migrate malfunction

Replica set can automatically failover. If primary is dropped or no response, but the most of replica members can link to each other, the new primary will be voted.
In most cases, when the primary is dropped, unavailable or is not suitable for primary,failover will be automatically start in few seconds without admin intervention.

There are few reasons if mongodb cannot migrate malfunction:

  • The number of remainning members is less than half of the replca set
  • no eligible primary member

Deployment strategy

The minimum replica set recommended for three members of the collection,one for primary and other two for secondary.

If there are more than three members in the replica set, it must follow these conditions:

  • 1、There are an odd number of members participating in the voting. If there are even voting members, deploy an arbiter to change the number to an odd number.
  • 2、After version 3.0.0 , the max node number is 50. It’s 12 before.
  • 3、If you do not want some members to become the primary, just set their priority to zero.

Ready for database

1
2
3
27017
27018
27019

prepare the ports 27017、27018、27019

Stop all mongod

1
$ sudo service mongod stop

Create database directory

1
$ sudo mkdir -p /data/mongodb/log /data/mongodb/rs0-0 /data/mongodb/rs0-1 /data/mongodb/rs0-2
  • Dir rs0-0,rs0-1,rs0-2 used to store the database file.

Create mongodb instance

1
2
3
$ sudo mongod --port 27017 --dbpath /data/mongodb/rs0-0 --replSet rs0 --smallfiles --oplogSize 128 --fork --logpath=/data/mongodb/log/271017.log
$ sudo mongod --port 27018 --dbpath /data/mongodb/rs0-1 --replSet rs0 --smallfiles --oplogSize 128 --fork --logpath=/data/mongodb/log/271018.log
$ sudo mongod --port 27019 --dbpath /data/mongodb/rs0-2 --replSet rs0 --smallfiles --oplogSize 128 --fork --logpath=/data/mongodb/log/271019.log
  • Create three nodes belong the replica set named rs0, and the data directory for each node is specified by ‘-dbpath’.
    ‘-smallfiles’ and ‘-oplogSize’ reduce the amount of disk space used by each mongod instance.
  • Mongodb also provides a daemon background way to start. Just add a ‘–fork’, but it must have the ‘–logpath’ parameter.
  • The unit of ‘–oplogsize’ is M

Connect to database

1
$ mongo --port 27017

Init replica set

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
> rsconf = {
"_id" : "rs0",
"members" : [
{
"_id" : 0,
"host" : "127.0.0.1:27017"
},
{
"_id" : 1,
"host" : "127.0.0.1:27018"
},
{
"_id" : 2,
"host" : "127.0.0.1:27019"
}
]
}
> rs.initiate( rsconf )
{ "ok" : 1 }

Check config result

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
rs0:OTHER> rs.conf()
{
"_id" : "rs0",
"version" : 1,
"members" : [
{
"_id" : 0,
"host" : "127.0.0.1:27017",
"arbiterOnly" : false,
"buildIndexes" : true,
"hidden" : false,
"priority" : 1,
"tags" : {

},
"slaveDelay" : 0,
"votes" : 1
},
{
"_id" : 1,
"host" : "127.0.0.1:27018",
"arbiterOnly" : false,
"buildIndexes" : true,
"hidden" : false,
"priority" : 1,
"tags" : {

},
"slaveDelay" : 0,
"votes" : 1
},
{
"_id" : 2,
"host" : "127.0.0.1:27019",
"arbiterOnly" : false,
"buildIndexes" : true,
"hidden" : false,
"priority" : 1,
"tags" : {

},
"slaveDelay" : 0,
"votes" : 1
}
],
"settings" : {
"chainingAllowed" : true,
"heartbeatTimeoutSecs" : 10,
"getLastErrorModes" : {

},
"getLastErrorDefaults" : {
"w" : 1,
"wtimeout" : 0
}
}
}

Check replica set 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
rs0:PRIMARY> rs.status()
{
"set" : "rs0",
"date" : ISODate("2017-03-23T08:23:05.564Z"),
"myState" : 1,
"members" : [
{
"_id" : 0,
"name" : "127.0.0.1:27017",
"health" : 1,
"state" : 1,
"stateStr" : "PRIMARY",
"uptime" : 144,
"optime" : Timestamp(1509438130, 1),
"optimeDate" : ISODate("2017-03-23T08:22:10Z"),
"electionTime" : Timestamp(1509438134, 1),
"electionDate" : ISODate("2017-03-23T08:22:14Z"),
"configVersion" : 1,
"self" : true
},
{
"_id" : 1,
"name" : "127.0.0.1:27018",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 54,
"optime" : Timestamp(1509438130, 1),
"optimeDate" : ISODate("2017-03-23T08:22:10Z"),
"lastHeartbeat" : ISODate("2017-03-23T08:23:04.993Z"),
"lastHeartbeatRecv" : ISODate("2017-03-23T08:23:04.993Z"),
"pingMs" : 0,
"lastHeartbeatMessage" : "could not find member to sync from",
"configVersion" : 1
},
{
"_id" : 2,
"name" : "127.0.0.1:27019",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 54,
"optime" : Timestamp(1509438130, 1),
"optimeDate" : ISODate("2017-03-23T08:22:10Z"),
"lastHeartbeat" : ISODate("2017-03-23T08:23:04.994Z"),
"lastHeartbeatRecv" : ISODate("2017-03-23T08:23:04.993Z"),
"pingMs" : 0,
"lastHeartbeatMessage" : "could not find member to sync from",
"configVersion" : 1
}
],
"ok" : 1
}

It’s done of building replica set!

Check the sync

Insert data into the Primary (127.0.0.1:27017)

1
2
3
4
5
6
7
8
9
10
11
$ mongo --port 27017

$ show dbs
local 0.000GB

$ use app

$ db.test.insert({"name":"test data","value":1111})

$ db.test.find()
{ "_id" : ObjectId("57382a2641cff36fe7f3fc30"), "name" : "test data", "value" : 1111 }

New a terminal connect

1
2
3
4
5
6
7
8
$ mongo --port 27018

$ use app

$ db.getMongo().setSlaveOk()

$ db.test.find()
{ "_id" : ObjectId("57382a2641cff36fe7f3fc30"), "name" : "test data", "value" : 1111 }

  • It cannot use ‘db.test.find()’ to get data. Mongodb reads and writes data on primary node default, it does not allow read on replica node but can be set solve this problem.

ok,data has been synchronized!

Check for automatic failover

Shutdown the main node Primary:

1
2
3
4
5
6
7
8
9
10
11
12
13
$ mongo --port 27017

$ use admin
switched to db admin

$ db.shutdownServer()
2017-03-23T08:24:40.887+0000 I NETWORK DBClientCursor::init call() failed
server should be down...
2017-03-23T08:24:40.891+0000 I NETWORK trying reconnect to 127.0.0.1:27017 (127.0.0.1) failed
2017-03-23T08:24:40.892+0000 I NETWORK reconnect 127.0.0.1:27017 (127.0.0.1) ok
2017-03-23T08:24:41.066+0000 I NETWORK Socket recv() errno:104 Connection reset by peer 127.0.0.1:27017
2017-03-23T08:24:41.067+0000 I NETWORK SocketException: remote: 127.0.0.1:27017 error: 9001 socket exception [RECV_ERROR] server [127.0.0.1:27017]
2017-03-23T08:24:41.068+0000 I NETWORK DBClientCursor::init call() failed

Entry another node:

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
$ mongo --port 27018

rs0:PRIMARY> rs.status()
{
"set" : "rs0",
"date" : ISODate("2017-03-23T08:26:22.753Z"),
"myState" : 1,
"members" : [
{
"_id" : 0,
"name" : "127.0.0.1:27017",
"health" : 0,
"state" : 8,
"stateStr" : "(not reachable/healthy)",
"uptime" : 0,
"optime" : Timestamp(0, 0),
"optimeDate" : ISODate("1970-01-01T00:00:00Z"),
"lastHeartbeat" : ISODate("2017-03-23T08:26:21.186Z"),
"lastHeartbeatRecv" : ISODate("2017-03-23T08:24:39.063Z"),
"pingMs" : 0,
"lastHeartbeatMessage" : "Failed attempt to connect to 127.0.0.1:27017; couldn't connect to server 127.0.0.1:27017 (127.0.0.1), connection attempt failed",
"configVersion" : -1
},
{
"_id" : 1,
"name" : "127.0.0.1:27018",
"health" : 1,
"state" : 1,
"stateStr" : "PRIMARY",
"uptime" : 312,
"optime" : Timestamp(1509438230, 2),
"optimeDate" : ISODate("2017-03-23T08:23:50Z"),
"electionTime" : Timestamp(1509438281, 1),
"electionDate" : ISODate("2017-03-23T08:24:41Z"),
"configVersion" : 1,
"self" : true
},
{
"_id" : 2,
"name" : "127.0.0.1:27019",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 249,
"optime" : Timestamp(1509438230, 2),
"optimeDate" : ISODate("2017-03-23T08:23:50Z"),
"lastHeartbeat" : ISODate("2017-03-23T08:26:21.134Z"),
"lastHeartbeatRecv" : ISODate("2017-03-23T08:26:21.134Z"),
"pingMs" : 0,
"configVersion" : 1
}
],
"ok" : 1
}

The node 127.0.0.1:27017 here can’t be reachable.
The node 127.0.0.1:27018 has been selected to be the new primary node.So automatic failover is successful.

Add a new node

1
2
$ sudo mkdir -p /data/mongodb/rs0-3
$ sudo mongod --port 27020 --dbpath /data/mongodb/rs0-3 --replSet rs0 --smallfiles --oplogSize 128 --fork --logpath=/data/mongodb/log/271020.log

Entry the primary node

1
$ mongo --port 27018

1
2
3
rs0:PRIMARY> rs.add("127.0.0.1:27020")
{ "ok" : 1 }
2017-03-23T08:30:54.755+0000 I NETWORK reconnect 127.0.0.1:27018 (127.0.0.1) ok

We can see that node has been added success.

Remove a node

1
2
rs0:PRIMARY> rs.remove("127.0.0.1:27020")
{ "ok" : 1 }

Manually change the primary node

To make the node ‘s priority become the maximum, this node will become the primary node:

1
2
3
4
5
6
7
8
9
10
rs0:PRIMARY> conf = rs.conf()
{
...

}

rs0:PRIMARY> conf.members[3].priority = 2
2

rs0:PRIMARY> rs.reconfig(conf)
Share