测试一
从节点宕机 集群依然可以正常使用,可以读写操作。
docker ps
三个容器均工作正常 (mongo01为主库,mongo02,mongo01为复制库)
此时手动停止mongo02容器
docker stop mongo02
进入容器,测试读写是否正常
主库插入
rs0:PRIMARY> use test
switched to db test
rs0:PRIMARY> db.user.insert({"id":1002,"name":"lisi"})
WriteResult({ "nInserted" : 1 })
复制库读取
rs0:SECONDARY> use test
switched to db test
rs0:SECONDARY> db.user.find()
{ "_id" : ObjectId("5f90f9c2d5a6806dd78d4879"), "id" : 1001, "name" : "zhangsan" }
{ "_id" : ObjectId("5f90fce6eaa4dcf95a6efb6f"), "id" : 1002, "name" : "lisi" }
测试二
主节点宕机 选举出新的主节点继续提供服务
我们开启mongo02
docker start mongo02
关闭主库
docker stop mongo01
进入容器,查看复制集状态
docker exec -it mongo02 /bin/bash
mongo
rs.status()
响应如下,可以看到节点一已经下线了,节点二被选举为主节点
{
"set" : "rs0",
"date" : ISODate("2020-10-22T03:36:10.917Z"),
"myState" : 1,
"term" : NumberLong(2),
"syncSourceHost" : "",
"syncSourceId" : -1,
"heartbeatIntervalMillis" : NumberLong(2000),
"majorityVoteCount" : 2,
"writeMajorityCount" : 2,
"votingMembersCount" : 3,
"writableVotingMembersCount" : 3,
"optimes" : {
"lastCommittedOpTime" : {
"ts" : Timestamp(1603337761, 1),
"t" : NumberLong(2)
},
"lastCommittedWallTime" : ISODate("2020-10-22T03:36:01.825Z"),
"readConcernMajorityOpTime" : {
"ts" : Timestamp(1603337761, 1),
"t" : NumberLong(2)
},
"readConcernMajorityWallTime" : ISODate("2020-10-22T03:36:01.825Z"),
"appliedOpTime" : {
"ts" : Timestamp(1603337761, 1),
"t" : NumberLong(2)
},
"durableOpTime" : {
"ts" : Timestamp(1603337761, 1),
"t" : NumberLong(2)
},
"lastAppliedWallTime" : ISODate("2020-10-22T03:36:01.825Z"),
"lastDurableWallTime" : ISODate("2020-10-22T03:36:01.825Z")
},
"lastStableRecoveryTimestamp" : Timestamp(1603337705, 1),
"electionCandidateMetrics" : {
"lastElectionReason" : "stepUpRequestSkipDryRun",
"lastElectionDate" : ISODate("2020-10-22T03:34:00.775Z"),
"electionTerm" : NumberLong(2),
"lastCommittedOpTimeAtElection" : {
"ts" : Timestamp(1603337639, 1),
"t" : NumberLong(1)
},
"lastSeenOpTimeAtElection" : {
"ts" : Timestamp(1603337639, 1),
"t" : NumberLong(1)
},
"numVotesNeeded" : 2,
"priorityAtElection" : 1,
"electionTimeoutMillis" : NumberLong(10000),
"priorPrimaryMemberId" : 0,
"numCatchUpOps" : NumberLong(0),
"newTermStartDate" : ISODate("2020-10-22T03:34:01.808Z"),
"wMajorityWriteAvailabilityDate" : ISODate("2020-10-22T03:34:02.794Z")
},
"members" : [
{
"_id" : 0,
"name" : "192.168.130.128: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-10-22T03:36:10.024Z"),
"lastHeartbeatRecv" : ISODate("2020-10-22T03:34:00.276Z"),
"pingMs" : NumberLong(0),
"lastHeartbeatMessage" : "Error connecting to 192.168.130.128:27017 :: caused by :: Connection refused",
"syncSourceHost" : "",
"syncSourceId" : -1,
"infoMessage" : "",
"configVersion" : 1,
"configTerm" : 1
},
{
"_id" : 1,
"name" : "192.168.130.128:27018",
"health" : 1,
"state" : 1,
"stateStr" : "PRIMARY",
"uptime" : 176,
"optime" : {
"ts" : Timestamp(1603337761, 1),
"t" : NumberLong(2)
},
"optimeDate" : ISODate("2020-10-22T03:36:01Z"),
"syncSourceHost" : "",
"syncSourceId" : -1,
"infoMessage" : "",
"electionTime" : Timestamp(1603337640, 1),
"electionDate" : ISODate("2020-10-22T03:34:00Z"),
"configVersion" : 1,
"configTerm" : 2,
"self" : true,
"lastHeartbeatMessage" : ""
},
{
"_id" : 2,
"name" : "192.168.130.128:27019",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 174,
"optime" : {
"ts" : Timestamp(1603337761, 1),
"t" : NumberLong(2)
},
"optimeDurable" : {
"ts" : Timestamp(1603337761, 1),
"t" : NumberLong(2)
},
"optimeDate" : ISODate("2020-10-22T03:36:01Z"),
"optimeDurableDate" : ISODate("2020-10-22T03:36:01Z"),
"lastHeartbeat" : ISODate("2020-10-22T03:36:09.922Z"),
"lastHeartbeatRecv" : ISODate("2020-10-22T03:36:10.907Z"),
"pingMs" : NumberLong(0),
"lastHeartbeatMessage" : "",
"syncSourceHost" : "192.168.130.128:27018",
"syncSourceId" : 1,
"infoMessage" : "",
"configVersion" : 1,
"configTerm" : 2
}
],
"ok" : 1,
"$clusterTime" : {
"clusterTime" : Timestamp(1603337761, 1),
"signature" : {
"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"keyId" : NumberLong(0)
}
},
"operationTime" : Timestamp(1603337761, 1)
}
测试三
停止集群中的2个节点 当前集群无法选举出Priamry,无法提供写操作,只能进行读操作
此时已经只有两个节点(一主一从)
我们停止主节点
docker stop mongo02
进入mongo03容器
docker exec -it mongo03 /bin/bash
mongo
可以看到节点三仍然是从节点。
测试四
增加arbiter节点
当集群中的节点数为偶数时,如一主一从情况下,任意一节点宕机都无法选举出Priamry,无法提供写操作,加入 arbiter节点后即可解决该问题。
我们开启mongo02,mongo01容器
docker start mongo02
此时为一主两从
创建一个新的容器作为arbiter节点
docker create --name mongo04 -p 27020:27017 -v mongo-data-04:/data/db mongo -replSet "rs0" --bind_ip_all
docker start mongo04
在主节点移除一个节点
rs.remove("192.168.130.128:27017")
响应
{
"ok" : 1,
"$clusterTime" : {
"clusterTime" : Timestamp(1603338733, 1),
"signature" : {
"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"keyId" : NumberLong(0)
}
},
"operationTime" : Timestamp(1603338733, 1)
}
ps:添加节点
rs.add("192.168.130.128:27017");
此时为一主一从(mongo03为主节点)
加入arbiter节点
rs.addArb("192.168.130.128:27020")
响应
{
"ok" : 1,
"$clusterTime" : {
"clusterTime" : Timestamp(1603338259, 1),
"signature" : {
"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"keyId" : NumberLong(0)
}
},
"operationTime" : Timestamp(1603338259, 1)
}
此时停止主节点(mongo03)
docker stop mongo03
进入mongo02
docker exec -it mongo02 /bin/bash
mongo
已成为主节点