Mongodb — replica set

Time:2020-11-22

MongoDB Replica Sets

brief introduction

MongoDBReplica sets in(Replica Set)Is a group that maintains the same datasetmongodService. Replica sets provide redundancy and high availability and are the foundation of all production deployments.

It can also be said that a replica set is similar to a master-slave cluster with automatic troubleshooting. Generally speaking, multiple machines are used for asynchronous synchronization of the same data, so that multiple machines have multiple copies of the same data, and when the main database is down, it automatically switches other backup servers to be the primary database without user intervention. Moreover, the replica server can be used as a read-only server to realize the separation of read and write and increase the load.

1 redundancy and data availability

Replication provides redundancy and improves data availability. By providing multiple copies of data on different database servers, replication provides a certain level of fault tolerance to prevent the loss of a single database server.

In some cases, replication can provide increased read performance because clients can send read operations to different services, and maintaining data copies in different data centers can increase the data location and availability of distributed applications.

2 replication in mongodb

A replica set is a group that maintains the same datasetmongodexample. The replica set contains multiple data hosting nodes and an optional quorum node. In the node that carries the data, one and only one member is regarded as the master node, while the other nodes are regarded as the to (slave) node.

The master node receives all operations. A replica set can only have one write that is primarily able to confirm that it has {W: “most”} write concerns; although in some cases, anothermongodFor the time being, examples may think that they are also major. It mainly records all changes of the dataset in its operation log, that isoplog

3 difference between master-slave replication and replica set

The biggest difference between a master-slave cluster and a replica set is that there is no fixed “primary node” in the replica set. The whole cluster will select a “master node”. After it is down, it will select other nodes from the remaining slave nodes as the “primary node”. The replica set always has an active point (primary and secondary) and one or more backup nodes (slave and secondary)

 

Three roles of replica set

There are two types of replica sets and three roles

There are two types:

  • Primary node type: the main connection of data operation takes you, read and write.
  • Secondary node type: data redundant backup node, which can be read or elected.

Three roles:

Primary: the primary receives all write operations. It’s the master node.

Replicate: the slave node maintains the same data set through replication operation, that is, backup data. It is not allowed to leak, but can be read (but needs to be configured). Is a default slave node type.

Arbiter: does not keep a copy of any data, only has the function of voting. Of course, the arbitration server can also be maintained as part of the replica set, that is, the replica member colleagues can also be arbitrators. It is also a slave node type.

 

Build replica set cluster

One master, one copy and one arbitration

Here we build on a machine and implement it through multi port mode

 

Create master node

1. Create data storage and log storage directory

# mkdir -p /data/replica_sets/myrs_27017/log
# mkdir -p /data/replica_sets/myrs_27017/data/db

2. Create or modify the configuration file

# vim /data/replica_sets/myrs_27017/mongod.conf 
systemLog:
    #The destination of the log output is specified as a file
    destination: file
    #Log storage directory
    path: "/data/replica_sets/myrs_27017/log/mongod.log"
    #When the mongos or mongod instance restarts, mongos or mongod appends new entries to the end of the existing log file
    logAppend: true
storage:
    #The directory in which the mongod instance stores its data
    dbPath: "/data/replica_sets/myrs_27017/data/db"
    journal:
        #Enabling or disabling persistent logging ensures that data files remain valid and recoverable 
        enabled: true
processManagement:
    #Enables the daemons mode to run mongos or mongod processes in the background
    fork: true
    #Specifies the file location to hold the process ID of the mongos or mongod process
    pidFilePath: "/data/replica_sets/myrs_27017/log/mongod.pid"
net:
    #Service instance binding IP
    bindIp: 127.0.0.1,10.10.10.11
    #Service instance binding port
    port: 27017
replication:
    #The name of the replica set
    replSetName: myrs

3. Start the node service

# mongod -f /data/replica_sets/myrs_27017/mongod.conf 
about to fork child process, waiting until server is ready for connections.
forked process: 23945
child process started successfully, parent exiting

 

Create replica node

1. Create data storage and log storage directory

# mkdir -p /data/replica_sets/myrs_27018/log
# mkdir -p /data/replica_sets/myrs_27018/data/db

2. Create or modify the configuration file

# vim /data/replica_sets/myrs_27018/mongod.conf 
systemLog:
    #The destination of the log output is specified as a file
    destination: file
    #Log storage directory
    path: "/data/replica_sets/myrs_27018/log/mongod.log"
    #When the mongos or mongod instance restarts, mongos or mongod appends new entries to the end of the existing log file
    logAppend: true
storage:
    #The directory in which the mongod instance stores its data
    dbPath: "/data/replica_sets/myrs_27018/data/db"
    journal:
        #Enabling or disabling persistent logging ensures that data files remain valid and recoverable 
        enabled: true
processManagement:
    #Enables the daemons mode to run mongos or mongod processes in the background
    fork: true
    #Specifies the file location to hold the process ID of the mongos or mongod process
    pidFilePath: "/data/replica_sets/myrs_27018/log/mongod.pid"
net:
    #Service instance binding IP
    bindIp: 127.0.0.1,10.10.10.11
    #Service instance binding port
    port: 27018
replication:
    #The name of the replica set
    replSetName: myrs

3. Start the node service

# mongod -f /data/replica_sets/myrs_27018/mongod.conf 
about to fork child process, waiting until server is ready for connections.
forked process: 24174
child process started successfully, parent exiting

 

Create arbitration node

1. Create data storage and log storage directory

# mkdir -p /data/replica_sets/myrs_27019/log
# mkdir -p /data/replica_sets/myrs_27019/data/db

2. Create or modify the configuration file

# vim /data/replica_sets/myrs_27019/mongod.conf
systemLog:
    #The destination of the log output is specified as a file
    destination: file
    #Log storage directory
    path: "/data/replica_sets/myrs_27019/log/mongod.log"
    #When the mongos or mongod instance restarts, mongos or mongod appends new entries to the end of the existing log file
    logAppend: true
storage:
    #The directory in which the mongod instance stores its data
    dbPath: "/data/replica_sets/myrs_27019/data/db"
    journal:
        #Enabling or disabling persistent logging ensures that data files remain valid and recoverable 
        enabled: true
processManagement:
    #Enables the daemons mode to run mongos or mongod processes in the background
    fork: true
    #Specifies the file location to hold the process ID of the mongos or mongod process
    pidFilePath: "/data/replica_sets/myrs_27019/log/mongod.pid"
net:
    #Service instance binding IP
    bindIp: 127.0.0.1,10.10.10.11
    #Service instance binding port
    port: 27019
replication:
    #The name of the replica set
    replSetName: myrs

3. Start the node service

# mongod -f /data/replica_sets/myrs_27019/mongod.conf 
about to fork child process, waiting until server is ready for connections.
forked process: 24441
child process started successfully, parent exiting

 

Initialize configuration replica set

1. Use the client command to connect any node and initialize the master node (27017 is selected here)

# mongo --host=10.10.10.11 --port=27017

Note: after connecting, many commands cannot be used, such asshow dbsThe replica set must be initialized

2. Initialize a new replica set (command:rs.initiate()

> rs.initiate()
{
	"info2" : "no configuration specified. Using a default configuration for the set",
	"me" : "10.10.10.11:27017",
	"ok" : 1,
	"$clusterTime" : {
		"clusterTime" : Timestamp(1604913568, 1),
		"signature" : {
			"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
			"keyId" : NumberLong(0)
		}
	},
	"operationTime" : Timestamp(1604913568, 1)
}
myrs:SECONDARY> 
myrs:PRIMARY>

remarks:

1)"ok"The value of 1 indicates that the creation is successful.

2) The command line prompt changes to a slave node role, which cannot be read or written by default. Wait a moment, enter, and become the master node.

 

View replica set configuration

Returns the document that contains the current replica set configuration.

Grammar:rs.conf(configuration)

remarks:

rs.config()Is an alias for the method.

Configuration: optional. If not configured, the default master configuration is used.

Example: performing the default node configuration for the current node in the replica set on 27017

myrs:PRIMARY> rs.conf()
{
	"_id" : "myrs",
	"version" : 1,
	"term" : 1,
	"protocolVersion" : NumberLong(1),
	"writeConcernMajorityJournalDefault" : true,
	"members" : [
		{
			"_id" : 0,
			"host" : "10.10.10.11:27017",
			"arbiterOnly" : false,
			"buildIndexes" : true,
			"hidden" : false,
			"priority" : 1,
			"tags" : {
				
			},
			"slaveDelay" : NumberLong(0),
			"votes" : 1
		}
	],
	"settings" : {
		"chainingAllowed" : true,
		"heartbeatIntervalMillis" : 2000,
		"heartbeatTimeoutSecs" : 10,
		"electionTimeoutMillis" : 10000,
		"catchUpTimeoutMillis" : -1,
		"catchUpTakeoverDelayMillis" : 30000,
		"getLastErrorModes" : {
			
		},
		"getLastErrorDefaults" : {
			"w" : 1,
			"wtimeout" : 0
		},
		"replicaSetId" : ObjectId("5fa909a07e34d2b6fa2e54a1")
	}
}

explain:

1)"_id" : "myrs": the primary key value of the configuration data store of the replica set. By default, it is the name of the replica set

2)"members": replica set member array, in this case, there is only one:"host" : "10.10.10.11:27017", the member is not a quorum node:"arbiterOnly" : false, priority (weight value):"priority" : 1

3)"settings": parameter configuration of replica set

Tip: the view command of replica set configuration is essentially a querysystem.replsetData in the table of:

myrs:PRIMARY> use local
switched to db local
myrs:PRIMARY> show collections
oplog.rs
replset.election
replset.initialSyncId
replset.minvalid
replset.oplogTruncateAfterPoint
startup_log
system.replset
system.rollback.id
myrs:PRIMARY> db.system.replset.find()
{ "_id" : "myrs", "version" : 1, "term" : 1, "protocolVersion" : NumberLong(1), "writeConcernMajorityJournalDefault" : true, "members" : [ { "_id" : 0, "host" : "10.10.10.11:27017", "arbiterOnly" : false, "buildIndexes" : true, "hidden" : false, "priority" : 1, "tags" : {  }, "slaveDelay" : NumberLong(0), "votes" : 1 } ], "settings" : { "chainingAllowed" : true, "heartbeatIntervalMillis" : 2000, "heartbeatTimeoutSecs" : 10, "electionTimeoutMillis" : 10000, "catchUpTimeoutMillis" : -1, "catchUpTakeoverDelayMillis" : 30000, "getLastErrorModes" : {  }, "getLastErrorDefaults" : { "w" : 1, "wtimeout" : 0 }, "replicaSetId" : ObjectId("5fa909a07e34d2b6fa2e54a1") } }

 

View the status of a replica set

Description: the document containing status information is returned. The data obtained from heartbeat packets sent by other members of the replica set reflects the current status of the replica set

Grammar:rs.status()

View replica set status on 27017

myrs:PRIMARY> rs.status()
{
	"set" : "myrs",
	"date" : ISODate("2020-11-10T01:15:18.661Z"),
	"myState" : 1,
	"term" : NumberLong(1),
	"syncSourceHost" : "",
	"syncSourceId" : -1,
	"heartbeatIntervalMillis" : NumberLong(2000),
	"majorityVoteCount" : 1,
	"writeMajorityCount" : 1,
	"votingMembersCount" : 1,
	"writableVotingMembersCount" : 1,
	"optimes" : {
		"lastCommittedOpTime" : {
			"ts" : Timestamp(1604970915, 1),
			"t" : NumberLong(1)
		},
		"lastCommittedWallTime" : ISODate("2020-11-10T01:15:15.402Z"),
		"readConcernMajorityOpTime" : {
			"ts" : Timestamp(1604970915, 1),
			"t" : NumberLong(1)
		},
		"readConcernMajorityWallTime" : ISODate("2020-11-10T01:15:15.402Z"),
		"appliedOpTime" : {
			"ts" : Timestamp(1604970915, 1),
			"t" : NumberLong(1)
		},
		"durableOpTime" : {
			"ts" : Timestamp(1604970915, 1),
			"t" : NumberLong(1)
		},
		"lastAppliedWallTime" : ISODate("2020-11-10T01:15:15.402Z"),
		"lastDurableWallTime" : ISODate("2020-11-10T01:15:15.402Z")
	},
	"lastStableRecoveryTimestamp" : Timestamp(1604970895, 1),
	"electionCandidateMetrics" : {
		"lastElectionReason" : "electionTimeout",
		"lastElectionDate" : ISODate("2020-11-09T09:19:28.377Z"),
		"electionTerm" : NumberLong(1),
		"lastCommittedOpTimeAtElection" : {
			"ts" : Timestamp(0, 0),
			"t" : NumberLong(-1)
		},
		"lastSeenOpTimeAtElection" : {
			"ts" : Timestamp(1604913568, 1),
			"t" : NumberLong(-1)
		},
		"numVotesNeeded" : 1,
		"priorityAtElection" : 1,
		"electionTimeoutMillis" : NumberLong(10000),
		"newTermStartDate" : ISODate("2020-11-09T09:19:28.401Z"),
		"wMajorityWriteAvailabilityDate" : ISODate("2020-11-09T09:19:28.420Z")
	},
	"members" : [
		{
			"_id" : 0,
			"name" : "10.10.10.11:27017",
			"health" : 1,
			"state" : 1,
			"stateStr" : "PRIMARY",
			"uptime" : 57734,
			"optime" : {
				"ts" : Timestamp(1604970915, 1),
				"t" : NumberLong(1)
			},
			"optimeDate" : ISODate("2020-11-10T01:15:15Z"),
			"syncSourceHost" : "",
			"syncSourceId" : -1,
			"infoMessage" : "",
			"electionTime" : Timestamp(1604913568, 2),
			"electionDate" : ISODate("2020-11-09T09:19:28Z"),
			"configVersion" : 1,
			"configTerm" : 1,
			"self" : true,
			"lastHeartbeatMessage" : ""
		}
	],
	"ok" : 1,
	"$clusterTime" : {
		"clusterTime" : Timestamp(1604970915, 1),
		"signature" : {
			"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
			"keyId" : NumberLong(0)
		}
	},
	"operationTime" : Timestamp(1604970915, 1)
}

explain:

1)"set" : "myrs": the name of the replica set

2)"myState" : 1: state is normal

3)"members": replica set member array, in this case, there is only one:"name" : "10.10.10.11:27017", the role of the member is"stateStr" : "PRIMARY"The node is healthy:"health" : 1

 

Add replica from node

Add the slave node in the master node and add other members to the replica set

Grammar:

rs.add(host, arbiterOnly)
Parameter Type Description
host string or document The new member to add to the replica set. Specify as string or configuration document: 1) if it is a string, you need to specify the host name and optional port of the new member; 2) if it is a document, you need to specify the replica set member configuration document found in the members array. The host field must be specified in the member configuration document. See the following document for details: “configuration document of host member”
arbiterOnly boolean Optional. Only inUsed when the value is a string. If true, the host added is an arbiter.

Configuration document of host member:

{ 
	_id: , 
	host: , // required 
	arbiterOnly: , 
	buildIndexes: , 
	hidden: , 
	priority: , 
	tags: , 
	slaveDelay: , 
	votes:  
}

Add the replica node of 27018 to the replica set:

myrs:PRIMARY> rs.add("10.10.10.11:27018")
{
	"ok" : 1,
	"$clusterTime" : {
		"clusterTime" : Timestamp(1604975516, 1),
		"signature" : {
			"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
			"keyId" : NumberLong(0)
		}
	},
	"operationTime" : Timestamp(1604975516, 1)
}

explain:

1)"ok" : 1: description added successfully.

View replica set status

myrs:PRIMARY> rs.status()
{
	"set" : "myrs",
	"date" : ISODate("2020-11-10T02:33:54.698Z"),
	"myState" : 1,
	"term" : NumberLong(1),
	"syncSourceHost" : "",
	"syncSourceId" : -1,
	"heartbeatIntervalMillis" : NumberLong(2000),
	"majorityVoteCount" : 2,
	"writeMajorityCount" : 2,
	"votingMembersCount" : 2,
	"writableVotingMembersCount" : 2,
	"optimes" : {
		"lastCommittedOpTime" : {
			"ts" : Timestamp(1604975625, 1),
			"t" : NumberLong(1)
		},
		"lastCommittedWallTime" : ISODate("2020-11-10T02:33:45.868Z"),
		"readConcernMajorityOpTime" : {
			"ts" : Timestamp(1604975625, 1),
			"t" : NumberLong(1)
		},
		"readConcernMajorityWallTime" : ISODate("2020-11-10T02:33:45.868Z"),
		"appliedOpTime" : {
			"ts" : Timestamp(1604975625, 1),
			"t" : NumberLong(1)
		},
		"durableOpTime" : {
			"ts" : Timestamp(1604975625, 1),
			"t" : NumberLong(1)
		},
		"lastAppliedWallTime" : ISODate("2020-11-10T02:33:45.868Z"),
		"lastDurableWallTime" : ISODate("2020-11-10T02:33:45.868Z")
	},
	"lastStableRecoveryTimestamp" : Timestamp(1604975575, 1),
	"electionCandidateMetrics" : {
		"lastElectionReason" : "electionTimeout",
		"lastElectionDate" : ISODate("2020-11-09T09:19:28.377Z"),
		"electionTerm" : NumberLong(1),
		"lastCommittedOpTimeAtElection" : {
			"ts" : Timestamp(0, 0),
			"t" : NumberLong(-1)
		},
		"lastSeenOpTimeAtElection" : {
			"ts" : Timestamp(1604913568, 1),
			"t" : NumberLong(-1)
		},
		"numVotesNeeded" : 1,
		"priorityAtElection" : 1,
		"electionTimeoutMillis" : NumberLong(10000),
		"newTermStartDate" : ISODate("2020-11-09T09:19:28.401Z"),
		"wMajorityWriteAvailabilityDate" : ISODate("2020-11-09T09:19:28.420Z")
	},
	"members" : [
		{
			"_id" : 0,
			"name" : "10.10.10.11:27017",
			"health" : 1,
			"state" : 1,
			"stateStr" : "PRIMARY",
			"uptime" : 62450,
			"optime" : {
				"ts" : Timestamp(1604975625, 1),
				"t" : NumberLong(1)
			},
			"optimeDate" : ISODate("2020-11-10T02:33:45Z"),
			"syncSourceHost" : "",
			"syncSourceId" : -1,
			"infoMessage" : "",
			"electionTime" : Timestamp(1604913568, 2),
			"electionDate" : ISODate("2020-11-09T09:19:28Z"),
			"configVersion" : 2,
			"configTerm" : 1,
			"self" : true,
			"lastHeartbeatMessage" : ""
		},
		{
			"_id" : 1,
			"name" : "10.10.10.11:27018",
			"health" : 1,
			"state" : 2,
			"stateStr" : "SECONDARY",
			"uptime" : 117,
			"optime" : {
				"ts" : Timestamp(1604975625, 1),
				"t" : NumberLong(1)
			},
			"optimeDurable" : {
				"ts" : Timestamp(1604975625, 1),
				"t" : NumberLong(1)
			},
			"optimeDate" : ISODate("2020-11-10T02:33:45Z"),
			"optimeDurableDate" : ISODate("2020-11-10T02:33:45Z"),
			"lastHeartbeat" : ISODate("2020-11-10T02:33:52.778Z"),
			"lastHeartbeatRecv" : ISODate("2020-11-10T02:33:53.089Z"),
			"pingMs" : NumberLong(0),
			"lastHeartbeatMessage" : "",
			"syncSourceHost" : "10.10.10.11:27017",
			"syncSourceId" : 0,
			"infoMessage" : "",
			"configVersion" : 2,
			"configTerm" : 1
		}
	],
	"ok" : 1,
	"$clusterTime" : {
		"clusterTime" : Timestamp(1604975625, 1),
		"signature" : {
			"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
			"keyId" : NumberLong(0)
		}
	},
	"operationTime" : Timestamp(1604975625, 1)
}

explain:

1)"name" : "10.10.10.11:27018"Is the name of the second node whose role is"stateStr" : "SECONDARY"

 

Add arbitration node

Add a quorum node to the replica set at the master node

Grammar:

rs.addArb(host)

Add 27019 node to replica set as quorum node:

myrs:PRIMARY> rs.addArb("10.10.10.11:27019")
{
	"ok" : 1,
	"$clusterTime" : {
		"clusterTime" : Timestamp(1604989664, 1),
		"signature" : {
			"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
			"keyId" : NumberLong(0)
		}
	},
	"operationTime" : Timestamp(1604989664, 1)
}

explain:

1)"ok" : 1: description added successfully

To view the replica set status:

myrs:PRIMARY> rs.status()
{
	"set" : "myrs",
	"date" : ISODate("2020-11-10T06:28:31.102Z"),
	"myState" : 1,
	"term" : NumberLong(1),
	"syncSourceHost" : "",
	"syncSourceId" : -1,
	"heartbeatIntervalMillis" : NumberLong(2000),
	"majorityVoteCount" : 2,
	"writeMajorityCount" : 2,
	"votingMembersCount" : 3,
	"writableVotingMembersCount" : 2,
	"optimes" : {
		"lastCommittedOpTime" : {
			"ts" : Timestamp(1604989707, 1),
			"t" : NumberLong(1)
		},
		"lastCommittedWallTime" : ISODate("2020-11-10T06:28:27.292Z"),
		"readConcernMajorityOpTime" : {
			"ts" : Timestamp(1604989707, 1),
			"t" : NumberLong(1)
		},
		"readConcernMajorityWallTime" : ISODate("2020-11-10T06:28:27.292Z"),
		"appliedOpTime" : {
			"ts" : Timestamp(1604989707, 1),
			"t" : NumberLong(1)
		},
		"durableOpTime" : {
			"ts" : Timestamp(1604989707, 1),
			"t" : NumberLong(1)
		},
		"lastAppliedWallTime" : ISODate("2020-11-10T06:28:27.292Z"),
		"lastDurableWallTime" : ISODate("2020-11-10T06:28:27.292Z")
	},
	"lastStableRecoveryTimestamp" : Timestamp(1604989675, 1),
	"electionCandidateMetrics" : {
		"lastElectionReason" : "electionTimeout",
		"lastElectionDate" : ISODate("2020-11-09T09:19:28.377Z"),
		"electionTerm" : NumberLong(1),
		"lastCommittedOpTimeAtElection" : {
			"ts" : Timestamp(0, 0),
			"t" : NumberLong(-1)
		},
		"lastSeenOpTimeAtElection" : {
			"ts" : Timestamp(1604913568, 1),
			"t" : NumberLong(-1)
		},
		"numVotesNeeded" : 1,
		"priorityAtElection" : 1,
		"electionTimeoutMillis" : NumberLong(10000),
		"newTermStartDate" : ISODate("2020-11-09T09:19:28.401Z"),
		"wMajorityWriteAvailabilityDate" : ISODate("2020-11-09T09:19:28.420Z")
	},
	"members" : [
		{
			"_id" : 0,
			"name" : "10.10.10.11:27017",
			"health" : 1,
			"state" : 1,
			"stateStr" : "PRIMARY",
			"uptime" : 76527,
			"optime" : {
				"ts" : Timestamp(1604989707, 1),
				"t" : NumberLong(1)
			},
			"optimeDate" : ISODate("2020-11-10T06:28:27Z"),
			"syncSourceHost" : "",
			"syncSourceId" : -1,
			"infoMessage" : "",
			"electionTime" : Timestamp(1604913568, 2),
			"electionDate" : ISODate("2020-11-09T09:19:28Z"),
			"configVersion" : 3,
			"configTerm" : 1,
			"self" : true,
			"lastHeartbeatMessage" : ""
		},
		{
			"_id" : 1,
			"name" : "10.10.10.11:27018",
			"health" : 1,
			"state" : 2,
			"stateStr" : "SECONDARY",
			"uptime" : 14194,
			"optime" : {
				"ts" : Timestamp(1604989707, 1),
				"t" : NumberLong(1)
			},
			"optimeDurable" : {
				"ts" : Timestamp(1604989707, 1),
				"t" : NumberLong(1)
			},
			"optimeDate" : ISODate("2020-11-10T06:28:27Z"),
			"optimeDurableDate" : ISODate("2020-11-10T06:28:27Z"),
			"lastHeartbeat" : ISODate("2020-11-10T06:28:30.884Z"),
			"lastHeartbeatRecv" : ISODate("2020-11-10T06:28:30.897Z"),
			"pingMs" : NumberLong(0),
			"lastHeartbeatMessage" : "",
			"syncSourceHost" : "10.10.10.11:27017",
			"syncSourceId" : 0,
			"infoMessage" : "",
			"configVersion" : 3,
			"configTerm" : 1
		},
		{
			"_id" : 2,
			"name" : "10.10.10.11:27019",
			"health" : 1,
			"state" : 7,
			"stateStr" : "ARBITER",
			"uptime" : 46,
			"lastHeartbeat" : ISODate("2020-11-10T06:28:30.900Z"),
			"lastHeartbeatRecv" : ISODate("2020-11-10T06:28:30.917Z"),
			"pingMs" : NumberLong(0),
			"lastHeartbeatMessage" : "",
			"syncSourceHost" : "",
			"syncSourceId" : -1,
			"infoMessage" : "",
			"configVersion" : 3,
			"configTerm" : 1
		}
	],
	"ok" : 1,
	"$clusterTime" : {
		"clusterTime" : Timestamp(1604989707, 1),
		"signature" : {
			"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
			"keyId" : NumberLong(0)
		}
	},
	"operationTime" : Timestamp(1604989707, 1)
}

explain:

1)"name" : "10.10.10.11:27019"Is the name of the second node whose role is"stateStr" : "ARBITER"

 

Data read and write operations of replica set

Test the data reading and writing of three nodes with different roles.

1、Test the master node 27017, write and read data:

# mongo --host=10.10.10.11 --port=27017
myrs:PRIMARY> use collectest
switched to db collectest
myrs:PRIMARY> db
collectest
myrs:PRIMARY > db.collectest.insert ({"name": "Zhang San", "sex": "male", "age": 22, "userid": 1001, "created datetime": new date()})
WriteResult({ "nInserted" : 1 })
myrs:PRIMARY> 
myrs:PRIMARY> db.collectest.find()
{ "_ ID ": objectid (" 5faa3432f6e79c62c00e4d72 ")," name ":" Zhang San "," sex ":" male "," age ": 22," userid ": 1001," created datetime ": Isodate (" 2020-11-10t06:33:22.459z ")}
myrs:PRIMARY>

Note: through the test, we can find that the master node can read and write data.

2、Test slave node

# mongo --host=10.10.10.11 --port=27018
myrs:SECONDARY> show dbs
uncaught exception: Error: listDatabases failed:{
	"topologyVersion" : {
		"processId" : ObjectId("5fa909804c7cb6020458ce77"),
		"counter" : NumberLong(5)
	},
	"operationTime" : Timestamp(1605085202, 1),
	"ok" : 0,
	"errmsg" : "not master and slaveOk=false",
	"code" : 13435,
	"codeName" : "NotMasterNoSlaveOk",
	"$clusterTime" : {
		"clusterTime" : Timestamp(1605085202, 1),
		"signature" : {
			"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
			"keyId" : NumberLong(0)
		}
	}
} :
[email protected]/mongo/shell/utils.js:25:13
Mongo.prototype.getDBs/

The test found that the data for the collection could not be read. Currently, the slave node is only a backup, not a slave node. It can’t read data, nor write. Because by default, the slave node does not have read-write permission. You can increase the read permission, but you need to set it.

Set read operation permission:

rs.secondaryOk()
#Or
rs.secondaryOk(true)

For example, set the slave node to have read permission on 27018

myrs:SECONDARY> rs.secondaryOk()
myrs:SECONDARY> show dbs
admin       0.000GB
collectest  0.000GB
config      0.000GB
local       0.000GB
myrs:SECONDARY> use collectest
switched to db collectest
myrs:SECONDARY> show collections
collectest
myrs:SECONDARY> 
myrs:SECONDARY> db.collectest.find()
{ "_ ID ": objectid (" 5faa3432f6e79c62c00e4d72 ")," name ":" Zhang San "," sex ":" male "," age ": 22," userid ": 1001," created datetime ": Isodate (" 2020-11-10t06:33:22.459z ")}

Here, read-write separation is realized, so that the master node inserts data and never reads data.

If you want to cancel read access from the node:

myrs:SECONDARY> rs.secondaryOk(false)
myrs:SECONDARY> show dbs
uncaught exception: Error: listDatabases failed:{
	"topologyVersion" : {
		"processId" : ObjectId("5fa909804c7cb6020458ce77"),
		"counter" : NumberLong(5)
	},
	"operationTime" : Timestamp(1605086322, 1),
	"ok" : 0,
	"errmsg" : "not master and slaveOk=false",
	"code" : 13435,
	"codeName" : "NotMasterNoSlaveOk",
	"$clusterTime" : {
		"clusterTime" : Timestamp(1605086322, 1),
		"signature" : {
			"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
			"keyId" : NumberLong(0)
		}
	}
} :
[email protected]/mongo/shell/utils.js:25:13
Mongo.prototype.getDBs/

3、Test arbitration node, arbitration node will not put any business data, you can log in to view

# mongo --host=10.10.10.11 --port=27019
myrs:ARBITER> show dbs
uncaught exception: Error: listDatabases failed:{
	"topologyVersion" : {
		"processId" : ObjectId("5fa90b59bea51b269ba3eb82"),
		"counter" : NumberLong(3)
	},
	"ok" : 0,
	"errmsg" : "node is not in primary or recovering state",
	"code" : 13436,
	"codeName" : "NotMasterOrSecondary"
} :
[email protected]/mongo/shell/utils.js:25:13
Mongo.prototype.getDBs/

The test found that the arbitration node cannot view the data.

 

Election principle of master node

MongoDBIn the replica set, the primary node election will be automatically conducted. The trigger conditions for the primary node election are as follows:

1) Master node failure

2) Master node network unreachable (default heartbeat information is 10 seconds)

3) Manual intervention(rs.stepDown(600)

Once the election is triggered, the master node must be selected according to certain rules.

The election rule is based on the number of votes to decide who wins

  • The node with the highest number of votes and the majority of the members voted for the victory
  • If the number of votes is the same, and all of them get the vote of “majority” members, the node with new data wins. The old and new of data is through operation logoplogTo compare.

When getting the number of votes, priority(priority)The influence of parameters is significant. You can set the priority by setting the priority(priority)To set the extra number of votes. Priority is the weight, and the value is0-1000The higher the priority value, the more likely it is to obtain the majority of the members(votes)Number. Specifying a higher value makes a member more eligible to be a primary member, and a lower value makes a member less eligible.

By default, the priority is 1

myrs:SECONDARY> rs.conf()
{
	"_id" : "myrs",
	"version" : 3,
	"term" : 3,
	"protocolVersion" : NumberLong(1),
	"writeConcernMajorityJournalDefault" : true,
	"members" : [
		{
			"_id" : 0,
			"host" : "10.10.10.11:27017",
			"arbiterOnly" : false,
			"buildIndexes" : true,
			"hidden" : false,
			"priority" : 1,
			"tags" : {
				
			},
			"slaveDelay" : NumberLong(0),
			"votes" : 1
		},
		{
			"_id" : 1,
			"host" : "10.10.10.11:27018",
			"arbiterOnly" : false,
			"buildIndexes" : true,
			"hidden" : false,
			"priority" : 1,
			"tags" : {
				
			},
			"slaveDelay" : NumberLong(0),
			"votes" : 1
		},
		{
			"_id" : 2,
			"host" : "10.10.10.11:27019",
			"arbiterOnly" : true,
			"buildIndexes" : true,
			"hidden" : false,
			"priority" : 0,
			"tags" : {
				
			},
			"slaveDelay" : NumberLong(0),
			"votes" : 1
		}
	],
	"settings" : {
		"chainingAllowed" : true,
		"heartbeatIntervalMillis" : 2000,
		"heartbeatTimeoutSecs" : 10,
		"electionTimeoutMillis" : 10000,
		"catchUpTimeoutMillis" : -1,
		"catchUpTakeoverDelayMillis" : 30000,
		"getLastErrorModes" : {
			
		},
		"getLastErrorDefaults" : {
			"w" : 1,
			"wtimeout" : 0
		},
		"replicaSetId" : ObjectId("5fa909a07e34d2b6fa2e54a1")
	}
}

It can be seen from the above configuration information that the priority of the master node and the replica node is 1, that is, by default, both the master node and the replica node have one vote. For a single election node, the priority is 0. (Note: the official said that the priority of the election node must be 0, not other values. That is, they have no right to vote, but only have the right to vote)

 

Fault test

Replica node failure test

Shut down the 27018 replica node:

# ps -ef |grep mongo
root      23945      1  0 Nov10 ?        00:22:10 mongod -f /data/replica_sets/myrs_27017/mongod.conf
root      24174      1  0 Nov10 ?        00:22:33 mongod -f /data/replica_sets/myrs_27018/mongod.conf
root      24441      1  0 Nov10 ?        00:15:15 mongod -f /data/replica_sets/myrs_27019/mongod.conf
# kill -2 24174

Enter the master node 27017 to write data

# mongo --host=10.10.10.11 --port=27017
---
myrs:PRIMARY> use collectest
switched to db collectest
myrs:PRIMARY > db.collectest.insert ({"name": "Xiaobai", "sex", "female", "age": 20, "userid": 1002, "created datetime": new date()})
WriteResult({ "nInserted" : 1 })

Start the 27018 replica node and verify the data

# mongod -f /data/replica_sets/myrs_27018/mongod.conf
# mongo --host=10.10.10.11 --port=27018
myrs:SECONDARY> rs.secondaryOk()
myrs:SECONDARY> show dbs
admin       0.000GB
collectest  0.000GB
config      0.000GB
local       0.001GB
myrs:SECONDARY> use collectest
switched to db collectest
myrs:SECONDARY> db.collectest.find()
{ "_ ID ": objectid (" 5faa3432f6e79c62c00e4d72 ")," name ":" Zhang San "," sex ":" male "," age ": 22," userid ": 1001," created datetime ": Isodate (" 2020-11-10t06:33:22.459z ")}
{ "_ ID ": objectid (" 5facec10cca53c48154d261c "), name:" Xiaobai "," sex "," female "," age ": 20," userid ": 1002," created datetime ": Isodate (" 2020-11-12t08:02:24.915z ")}

Through the above test verification, we can find that when the replica node fails, the read and write of the primary node are not affected, andAfter the replica node is restored, the data written by the master node will be automatically synchronized to the slave node.

 

Master node fault test

Shut down master 27017

# ps -ef |grep mongo
root      23945      1  0 Nov10 ?        00:22:34 mongod -f /data/replica_sets/myrs_27017/mongod.conf
root      24441      1  0 Nov10 ?        00:15:27 mongod -f /data/replica_sets/myrs_27019/mongod.conf
root      50521      1  1 16:04 ?        00:00:16 mongod -f /data/replica_sets/myrs_27018/mongod.conf
# kill -2 23945

Log in to the replica node to view the cluster status

# mongo --host=10.10.10.11 --port=27018
myrs:PRIMARY> 
myrs:PRIMARY> rs.status()
{
	"set" : "myrs",
	"date" : ISODate("2020-11-12T08:30:11.791Z"),
	"myState" : 1,
	"term" : NumberLong(7),
	"syncSourceHost" : "",
	"syncSourceId" : -1,
	"heartbeatIntervalMillis" : NumberLong(2000),
	"majorityVoteCount" : 2,
	"writeMajorityCount" : 2,
	"votingMembersCount" : 3,
	"writableVotingMembersCount" : 2,
	"optimes" : {
		"lastCommittedOpTime" : {
			"ts" : Timestamp(1605169711, 1),
			"t" : NumberLong(5)
		},
		"lastCommittedWallTime" : ISODate("2020-11-12T08:28:31.364Z"),
		"readConcernMajorityOpTime" : {
			"ts" : Timestamp(1605169711, 1),
			"t" : NumberLong(5)
		},
		"readConcernMajorityWallTime" : ISODate("2020-11-12T08:28:31.364Z"),
		"appliedOpTime" : {
			"ts" : Timestamp(1605169802, 1),
			"t" : NumberLong(7)
		},
		"durableOpTime" : {
			"ts" : Timestamp(1605169802, 1),
			"t" : NumberLong(7)
		},
		"lastAppliedWallTime" : ISODate("2020-11-12T08:30:02.141Z"),
		"lastDurableWallTime" : ISODate("2020-11-12T08:30:02.141Z")
	},
	"lastStableRecoveryTimestamp" : Timestamp(1605169711, 1),
	"electionCandidateMetrics" : {
		"lastElectionReason" : "electionTimeout",
		"lastElectionDate" : ISODate("2020-11-12T08:28:42.106Z"),
		"electionTerm" : NumberLong(7),
		"lastCommittedOpTimeAtElection" : {
			"ts" : Timestamp(1605169711, 1),
			"t" : NumberLong(5)
		},
		"lastSeenOpTimeAtElection" : {
			"ts" : Timestamp(1605169711, 1),
			"t" : NumberLong(5)
		},
		"numVotesNeeded" : 2,
		"priorityAtElection" : 1,
		"electionTimeoutMillis" : NumberLong(10000),
		"numCatchUpOps" : NumberLong(0),
		"newTermStartDate" : ISODate("2020-11-12T08:28:42.125Z")
	},
	"members" : [
		{
			"_id" : 0,
			"name" : "10.10.10.11:27017",
			"health" : 0,
			"state" : 8,
			"stateStr" : "(not reachable/healthy)",
			"uptime" : 0,
			"optime" : {
				"ts" : Timestamp(0, 0),
				"t" : NumberLong(-1)
			},
			"optimeDurable" : {
				"ts" : Timestamp(0, 0),
				"t" : NumberLong(-1)
			},
			"optimeDate" : ISODate("1970-01-01T00:00:00Z"),
			"optimeDurableDate" : ISODate("1970-01-01T00:00:00Z"),
			"lastHeartbeat" : ISODate("2020-11-12T08:30:10.207Z"),
			"lastHeartbeatRecv" : ISODate("2020-11-12T08:28:31.380Z"),
			"pingMs" : NumberLong(0),
			"lastHeartbeatMessage" : "Error connecting to 10.10.10.11:27017 :: caused by :: Connection refused",
			"syncSourceHost" : "",
			"syncSourceId" : -1,
			"infoMessage" : "",
			"configVersion" : 3,
			"configTerm" : 5
		},
		{
			"_id" : 1,
			"name" : "10.10.10.11:27018",
			"health" : 1,
			"state" : 1,
			"stateStr" : "PRIMARY",
			"uptime" : 1537,
			"optime" : {
				"ts" : Timestamp(1605169802, 1),
				"t" : NumberLong(7)
			},
			"optimeDate" : ISODate("2020-11-12T08:30:02Z"),
			"syncSourceHost" : "",
			"syncSourceId" : -1,
			"infoMessage" : "",
			"electionTime" : Timestamp(1605169722, 1),
			"electionDate" : ISODate("2020-11-12T08:28:42Z"),
			"configVersion" : 3,
			"configTerm" : 7,
			"self" : true,
			"lastHeartbeatMessage" : ""
		},
		{
			"_id" : 2,
			"name" : "10.10.10.11:27019",
			"health" : 1,
			"state" : 7,
			"stateStr" : "ARBITER",
			"uptime" : 1534,
			"lastHeartbeat" : ISODate("2020-11-12T08:30:10.162Z"),
			"lastHeartbeatRecv" : ISODate("2020-11-12T08:30:10.165Z"),
			"pingMs" : NumberLong(0),
			"lastHeartbeatMessage" : "",
			"syncSourceHost" : "",
			"syncSourceId" : -1,
			"infoMessage" : "",
			"configVersion" : 3,
			"configTerm" : 7
		}
	],
	"ok" : 1,
	"$clusterTime" : {
		"clusterTime" : Timestamp(1605169802, 1),
		"signature" : {
			"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
			"keyId" : NumberLong(0)
		}
	},
	"operationTime" : Timestamp(1605169802, 1)
}

From the above view, the previous 27018 replica node has become the master node. Next, insert data into the replica node

myrs:PRIMARY> use collectest
switched to db collectest
myrs:PRIMARY > db.collectest.insert ({"name": "little Hey", "sex", "female", "age": 21, "userid": 1002, "created datetime": new date()})
WriteResult({ "nInserted" : 1 })

At this point, restart the 27017 node and check the status

# mongod -f /data/replica_sets/myrs_27017/mongod.conf
# mongo --host=10.10.10.11 --port=27017
myrs:SECONDARY> 
myrs:SECONDARY> rs.secondaryOk()
myrs:SECONDARY> use collectest
switched to db collectest
myrs:SECONDARY> db.collectest.find()
{ "_ ID ": objectid (" 5faa3432f6e79c62c00e4d72 ")," name ":" Zhang San "," sex ":" male "," age ": 22," userid ": 1001," created datetime ": Isodate (" 2020-11-10t06:33:22.459z ")}
{ "_ ID ": objectid (" 5facec10cca53c48154d261c "), name:" Xiaobai "," sex "," female "," age ": 20," userid ": 1002," created datetime ": Isodate (" 2020-11-12t08:02:24.915z ")}
{ "_ ID ": objectid (" 5facf32dfb5fe16aaf699d7d ")," name ":" Xiaohei "," sex ":" female "," age ": 21," userid ": 1002," created datetime ": Isodate (" 2020-11-12t08:32:45.919z ")}

Through the above test, we found that 27017 node has become a replica node, and after configuring the view permission, you can view the data.

Through the above test, the master and slave switch automatically, so the high availability is tried.

 

Arbitration node and master node failure

First turn off arbitration node 27019

Turn off the current master 27018

After logging in 27017, it is found that 27017 is still a slave node, and there is no master node in the replica set. At this time, the replica set is only in read state and cannot be written.

Why not vote? Because 27017 has no majority, i.e. no more than 2, it has only the default vote (priority is 1)

If you want to trigger an election, you can join any member.

  • If only 27019 arbitration node members are added, the master node must be 27017, because the arbitration node does not participate in the election, but participates in voting

  • If only 27018 nodes are added, an election will be held. Because 27017 and 27018 are both two votes, the master node is determined by who is new.