MongoDB Replica Set(docker方式)
1 介绍
MongoDB Replica Set中文名为副本集,通俗地讲是集群当中包含了多份数据,保证主节点挂掉了,备节点能继续提供数据服务,提供的前提就是数据需要和主节点一致。
Mongodb(M)表示主节点,Mongodb(S)表示备节点,Mongodb(A)表示仲裁节点(Arbiter)。主备节点存储数据,仲裁节点不存储数据。客户端同时连接主节点与备节点,不连接仲裁节点。
默认设置下,主节点提供所有增删查改服务,备节点不提供任何服务。但是可以通过设置使备节点提供查询服务,这样就可以减少主节点的压力,当客户端进行数据查询时,请求自动转到备节点上。这个设置叫做Read Preference Modes,同时Java客户端提供了简单的配置方式,可以不必直接对数据库进行操作。
仲裁节点是一种特殊的节点,它本身并不存储数据,主要的作用是决定哪一个备节点在主节点挂掉之后提升为主节点,所以客户端不需要连接此节点。这里虽然只有一个备节点,但是仍然需要一个仲裁节点来提升备节点级别。我开始也不相信必须要有仲裁节点,但是自己也试过没仲裁节点的话,主节点挂了备节点还是备节点,所以咱们还是需要它的。
2 部署MongoDB Replica Set
2.1 准备工作
部署环境:
| 角色 | 默认端口 | 映射主机端口 | |
| Master | 27017 | 37071 | |
| Slave1 | 27017 | 37072 | |
| Slave2 | 27017 | 37073 | |
| Arbiter1 | 27018 | 37074 | |
宿主机安装MongoDB Shell(MongoDB Shell版本与数据库版本一致),后面方便管理。
拉取MongoDB for Docker镜像
[root]# docker pull mongo:latest
生成keyfile文件(后面开启认证登录时需要)
[root]# mkdir -p /etc/mongodb
[root]# openssl rand -base64 765 > /etc/mongodb/key.file
[root]# chmod 400 /etc/mongodb/key.file
2.2 部署数据节点
创建配置文件mongod.conf
[root]# vi /etc/mongodb/mongod.conf
systemLog:
destination: file
path: "/data/db/mongod.log"
logAppend: true
storage:
dbPath: /data/db
wiredTiger:
engineConfig:
cacheSizeGB: 0.25
net:
bindIpAll: true
port: 27017
#security:
# keyFile: /data/db/key.file
# authorization: enabled
replication:
replSetName: replicas
oplogSizeMB: 2048
创建数据节点容器
[root]# docker run -d --name replica_db01 -p 37071:27017 -v /etc/mongodb/mongod.conf:/data/db/replica01.conf -v /etc/mongodb/key.file:/data/db/key.file mongo --config /data/db/replica01.conf
[root]# docker run -d --name replica_db02 -p 37072:27017 -v /etc/mongodb/mongod.conf:/data/db/replica02.conf -v /etc/mongodb/key.file:/data/db/key.file mongo --config /data/db/replica02.conf
[root]# docker run -d --name replica_db03 -p 37073:27017 -v /etc/mongodb/mongod.conf:/data/db/replica03.conf -v /etc/mongodb/key.file:/data/db/key.file mongo --config /data/db/replica03.conf
2.3 部署Arbiter节点
创建配置文件arbiter.conf
[root]# vi /etc/mongodb/arbiter.conf
systemLog:
destination: file
path: "/data/db/arbiter.log"
logAppend: true
storage:
dbPath: /data/db
wiredTiger:
engineConfig:
cacheSizeGB: 0.25
net:
bindIpAll: true
port: 27018
#security:
# keyFile: /data/db/key.file
# authorization: enabled
replication:
replSetName: replicas
oplogSizeMB: 2048
创建Arbiter节点容器
[root]# docker run -d --name replica_arbiter01 -p 37074:27017 -v /etc/mongodb/arbiter.conf:/data/db/arbiter01.conf -v /etc/mongodb/key.file:/data/db/key.file mongo --config /data/db/arbiter01.conf
2.4 创建副本集
初始化并创建副本集
> rs.initiate(
{
_id : "replicas",
members: [
{ _id : 0, host : "10.150.57.13:37071" },
{ _id : 1, host : "10.150.57.13:37072" },
{ _id : 2, host : "10.150.57.13:37073" },
{ _id : 3, host : "10.150.57.13:37074", arbiterOnly:true }
]
}
)
2.5 查看副本集信息
查看副本集信息
replicas:PRIMARY> rs.status()
{
"set" : "replicas",
"date" : ISODate("2022-01-18T02:58:22.833Z"),
"myState" : 1,
"term" : NumberLong(1),
"syncSourceHost" : "",
"syncSourceId" : -1,
"heartbeatIntervalMillis" : NumberLong(2000),
"majorityVoteCount" : 3,
"writeMajorityCount" : 3,
"votingMembersCount" : 4,
"writableVotingMembersCount" : 3,
"optimes" : {
"lastCommittedOpTime" : {
"ts" : Timestamp(1642474693, 1),
"t" : NumberLong(1)
},
"lastCommittedWallTime" : ISODate("2022-01-18T02:58:13.609Z"),
"readConcernMajorityOpTime" : {
"ts" : Timestamp(1642474693, 1),
"t" : NumberLong(1)
},
"appliedOpTime" : {
"ts" : Timestamp(1642474693, 1),
"t" : NumberLong(1)
},
"durableOpTime" : {
"ts" : Timestamp(1642474693, 1),
"t" : NumberLong(1)
},
"lastAppliedWallTime" : ISODate("2022-01-18T02:58:13.609Z"),
"lastDurableWallTime" : ISODate("2022-01-18T02:58:13.609Z")
},
"lastStableRecoveryTimestamp" : Timestamp(1642474663, 1),
"electionCandidateMetrics" : {
"lastElectionReason" : "electionTimeout",
"lastElectionDate" : ISODate("2022-01-18T02:56:03.593Z"),
"electionTerm" : NumberLong(1),
"lastCommittedOpTimeAtElection" : {
"ts" : Timestamp(1642474552, 1),
"t" : NumberLong(-1)
},
"lastSeenOpTimeAtElection" : {
"ts" : Timestamp(1642474552, 1),
"t" : NumberLong(-1)
},
"numVotesNeeded" : 3,
"priorityAtElection" : 1,
"electionTimeoutMillis" : NumberLong(10000),
"numCatchUpOps" : NumberLong(0),
"newTermStartDate" : ISODate("2022-01-18T02:56:03.603Z"),
"wMajorityWriteAvailabilityDate" : ISODate("2022-01-18T02:56:04.258Z")
},
"members" : [
{
"_id" : 0,
"name" : "10.150.57.13:37071",
"health" : 1,
"state" : 1,
"stateStr" : "PRIMARY",
"uptime" : 39455,
"optime" : {
"ts" : Timestamp(1642474693, 1),
"t" : NumberLong(1)
},
"optimeDate" : ISODate("2022-01-18T02:58:13Z"),
"lastAppliedWallTime" : ISODate("2022-01-18T02:58:13.609Z"),
"lastDurableWallTime" : ISODate("2022-01-18T02:58:13.609Z"),
"syncSourceHost" : "",
"syncSourceId" : -1,
"infoMessage" : "",
"electionTime" : Timestamp(1642474563, 1),
"electionDate" : ISODate("2022-01-18T02:56:03Z"),
"configVersion" : 1,
"configTerm" : 1,
"self" : true,
"lastHeartbeatMessage" : ""
},
{
"_id" : 1,
"name" : "10.150.57.13:37072",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 150,
"optime" : {
"ts" : Timestamp(1642474693, 1),
"t" : NumberLong(1)
},
"optimeDurable" : {
"ts" : Timestamp(1642474693, 1),
"t" : NumberLong(1)
},
"optimeDate" : ISODate("2022-01-18T02:58:13Z"),
"optimeDurableDate" : ISODate("2022-01-18T02:58:13Z"),
"lastAppliedWallTime" : ISODate("2022-01-18T02:58:13.609Z"),
"lastDurableWallTime" : ISODate("2022-01-18T02:58:13.609Z"),
"lastHeartbeat" : ISODate("2022-01-18T02:58:21.596Z"),
"lastHeartbeatRecv" : ISODate("2022-01-18T02:58:22.601Z"),
"pingMs" : NumberLong(0),
"lastHeartbeatMessage" : "",
"syncSourceHost" : "10.150.57.13:37071",
"syncSourceId" : 0,
"infoMessage" : "",
"configVersion" : 1,
"configTerm" : 1
},
{
"_id" : 2,
"name" : "10.150.57.13:37073",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 150,
"optime" : {
"ts" : Timestamp(1642474693, 1),
"t" : NumberLong(1)
},
"optimeDurable" : {
"ts" : Timestamp(1642474693, 1),
"t" : NumberLong(1)
},
"optimeDate" : ISODate("2022-01-18T02:58:13Z"),
"optimeDurableDate" : ISODate("2022-01-18T02:58:13Z"),
"lastAppliedWallTime" : ISODate("2022-01-18T02:58:13.609Z"),
"lastDurableWallTime" : ISODate("2022-01-18T02:58:13.609Z"),
"lastHeartbeat" : ISODate("2022-01-18T02:58:21.597Z"),
"lastHeartbeatRecv" : ISODate("2022-01-18T02:58:22.600Z"),
"pingMs" : NumberLong(0),
"lastHeartbeatMessage" : "",
"syncSourceHost" : "10.150.57.13:37071",
"syncSourceId" : 0,
"infoMessage" : "",
"configVersion" : 1,
"configTerm" : 1
},
{
"_id" : 3,
"name" : "10.150.57.13:37074",
"health" : 1,
"state" : 7,
"stateStr" : "ARBITER",
"uptime" : 150,
"lastHeartbeat" : ISODate("2022-01-18T02:58:21.597Z"),
"lastHeartbeatRecv" : ISODate("2022-01-18T02:58:21.600Z"),
"pingMs" : NumberLong(0),
"lastHeartbeatMessage" : "",
"syncSourceHost" : "",
"syncSourceId" : -1,
"infoMessage" : "",
"configVersion" : 1,
"configTerm" : 1
}
],
"ok" : 1,
"$clusterTime" : {
"clusterTime" : Timestamp(1642474693, 1),
"signature" : {
"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"keyId" : NumberLong(0)
}
},
"operationTime" : Timestamp(1642474693, 1)
}
确认哪个节点是Master
replicas:PRIMARY> rs.isMaster()
{
"topologyVersion" : {
"processId" : ObjectId("61e592afd305eeacf7ed8c65"),
"counter" : NumberLong(6)
},
"hosts" : [
"10.150.57.13:37071",
"10.150.57.13:37072",
"10.150.57.13:37073"
],
"arbiters" : [
"10.150.57.13:37074"
],
"setName" : "replicas",
"setVersion" : 1,
"ismaster" : true,
"secondary" : false,
"primary" : "10.150.57.13:37071",
"me" : "10.150.57.13:37071",
"electionId" : ObjectId("7fffffff0000000000000001"),
"lastWrite" : {
"opTime" : {
"ts" : Timestamp(1642474893, 1),
"t" : NumberLong(1)
},
"lastWriteDate" : ISODate("2022-01-18T03:01:33Z"),
"majorityOpTime" : {
"ts" : Timestamp(1642474893, 1),
"t" : NumberLong(1)
},
"majorityWriteDate" : ISODate("2022-01-18T03:01:33Z")
},
"maxBsonObjectSize" : 16777216,
"maxMessageSizeBytes" : 48000000,
"maxWriteBatchSize" : 100000,
"localTime" : ISODate("2022-01-18T03:01:35.509Z"),
"logicalSessionTimeoutMinutes" : 30,
"connectionId" : 2,
"minWireVersion" : 0,
"maxWireVersion" : 13,
"readOnly" : false,
"ok" : 1,
"$clusterTime" : {
"clusterTime" : Timestamp(1642474893, 1),
"signature" : {
"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"keyId" : NumberLong(0)
}
},
"operationTime" : Timestamp(1642474893, 1)
}
查看副本集配置信息
replicas:PRIMARY> rs.conf()
{
"_id" : "replicas",
"version" : 1,
"term" : 1,
"members" : [
{
"_id" : 0,
"host" : "10.150.57.13:37071",
"arbiterOnly" : false,
"buildIndexes" : true,
"hidden" : false,
"priority" : 1,
"tags" : {
},
"secondaryDelaySecs" : NumberLong(0),
"votes" : 1
},
{
"_id" : 1,
"host" : "10.150.57.13:37072",
"arbiterOnly" : false,
"buildIndexes" : true,
"hidden" : false,
"priority" : 1,
"tags" : {
},
"secondaryDelaySecs" : NumberLong(0),
"votes" : 1
},
{
"_id" : 2,
"host" : "10.150.57.13:37073",
"arbiterOnly" : false,
"buildIndexes" : true,
"hidden" : false,
"priority" : 1,
"tags" : {
},
"secondaryDelaySecs" : NumberLong(0),
"votes" : 1
},
{
"_id" : 3,
"host" : "10.150.57.13:37074",
"arbiterOnly" : true,
"buildIndexes" : true,
"hidden" : false,
"priority" : 0,
"tags" : {
},
"secondaryDelaySecs" : NumberLong(0),
"votes" : 1
}
],
"protocolVersion" : NumberLong(1),
"writeConcernMajorityJournalDefault" : true,
"settings" : {
"chainingAllowed" : true,
"heartbeatIntervalMillis" : 2000,
"heartbeatTimeoutSecs" : 10,
"electionTimeoutMillis" : 10000,
"catchUpTimeoutMillis" : -1,
"catchUpTakeoverDelayMillis" : 30000,
"getLastErrorModes" : {
},
"getLastErrorDefaults" : {
"w" : 1,
"wtimeout" : 0
},
"replicaSetId" : ObjectId("61e62c38d305eeacf7ed8f87")
}
}
3 MongoDB Replica Set测试
3.1 数据同步测试
Master端创建测试数据
[root]# mongo --port 37071
replicas:PRIMARY> use gaoyu
switched to db gaoyu
replicas:PRIMARY> db.t1.insert( { name : "gaoyu" } )
Slave1端查看数据是否同步
[root]# mongo --port 37072
replicas:SECONDARY> use gaoyu
switched to db gaoyu
replicas:SECONDARY> rs.secondaryOk() #开启Slave可读
replicas:SECONDARY> show collections
t1
replicas:SECONDARY> db.t1.find()
{ "_id" : ObjectId("61e6d385c8ca480d8b12f836"), "name" : "gaoyu" }
Slave2端查看数据是否同步
[root]# mongo --port 37073
replicas:SECONDARY> use gaoyu
switched to db gaoyu
replicas:SECONDARY> rs.secondaryOk() #开启Slave可读
replicas:SECONDARY> show collections
t1
replicas:SECONDARY> db.t1.find()
{ "_id" : ObjectId("61e6d385c8ca480d8b12f836"), "name" : "gaoyu" }
3.2 测试Master自动切换
查看哪个节点是Master,当前Master是10.150.57.13:37071
replicas:SECONDARY> rs.isMaster()
{
"topologyVersion" : {
"processId" : ObjectId("61e593430ae02c2941c3e53f"),
"counter" : NumberLong(6)
},
"hosts" : [
"10.150.57.13:37071",
"10.150.57.13:37072",
"10.150.57.13:37073"
],
"arbiters" : [
"10.150.57.13:37074"
],
"setName" : "replicas",
"setVersion" : 3,
"ismaster" : false,
"secondary" : true,
"primary" : "10.150.57.13:37071",
"me" : "10.150.57.13:37072",
"lastWrite" : {
"opTime" : {
"ts" : Timestamp(1642520214, 1),
"t" : NumberLong(1)
},
"lastWriteDate" : ISODate("2022-01-18T15:36:54Z"),
"majorityOpTime" : {
"ts" : Timestamp(1642520214, 1),
"t" : NumberLong(1)
},
"majorityWriteDate" : ISODate("2022-01-18T15:36:54Z")
},
"maxBsonObjectSize" : 16777216,
"maxMessageSizeBytes" : 48000000,
"maxWriteBatchSize" : 100000,
"localTime" : ISODate("2022-01-18T15:37:01.467Z"),
"logicalSessionTimeoutMinutes" : 30,
"connectionId" : 77,
"minWireVersion" : 0,
"maxWireVersion" : 13,
"readOnly" : false,
"ok" : 1,
"$clusterTime" : {
"clusterTime" : Timestamp(1642520214, 1),
"signature" : {
"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"keyId" : NumberLong(0)
}
},
"operationTime" : Timestamp(1642520214, 1)
}
手动关闭10.150.57.13:37071所对应的docker容器
[root]# docker stop replica_db01
查看哪个节点是Master
replicas:SECONDARY> rs.isMaster()
{
"topologyVersion" : {
"processId" : ObjectId("61e593430ae02c2941c3e53f"),
"counter" : NumberLong(7)
},
"hosts" : [
"10.150.57.13:37071",
"10.150.57.13:37072",
"10.150.57.13:37073"
],
"arbiters" : [
"10.150.57.13:37074"
],
"setName" : "replicas",
"setVersion" : 3,
"ismaster" : false,
"secondary" : true,
"primary" : "10.150.57.13:37073",
"me" : "10.150.57.13:37072",
"lastWrite" : {
"opTime" : {
"ts" : Timestamp(1642520464, 1),
"t" : NumberLong(3)
},
"lastWriteDate" : ISODate("2022-01-18T15:41:04Z"),
"majorityOpTime" : {
"ts" : Timestamp(1642520394, 1),
"t" : NumberLong(1)
},
"majorityWriteDate" : ISODate("2022-01-18T15:39:54Z")
},
"maxBsonObjectSize" : 16777216,
"maxMessageSizeBytes" : 48000000,
"maxWriteBatchSize" : 100000,
"localTime" : ISODate("2022-01-18T15:41:07.337Z"),
"logicalSessionTimeoutMinutes" : 30,
"connectionId" : 90,
"minWireVersion" : 0,
"maxWireVersion" : 13,
"readOnly" : false,
"ok" : 1,
"$clusterTime" : {
"clusterTime" : Timestamp(1642520464, 1),
"signature" : {
"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"keyId" : NumberLong(0)
}
},
"operationTime" : Timestamp(1642520464, 1)
}
可以看到10.150.57.13:37073已经成为Master。
4 Replica Set增/删节点
4.1 新增Arbiter节点
4.2 删除Arbiter节点
4.3 新增复制节点
4.4 删除复制节点
未完成,待更新。