一,简介
Mongodb复制集由一组Mongod实例(进程)组成,包含一个Primary节点和多个Secondary节点。
Mongodb Driver(客户端)的所有数据都写入Primary,Secondary从Primary同步写入的数据,以保持复制集内所有成员存储相同的数据集,实现数据的高可用。
使用场景
- 数据冗余,用做故障恢复使用,当发生硬件故障或者其它原因造成的宕机时,可以使用副本进行恢复。
- 读写分离,读的请求分流到副本上,减轻主节点的读压力。
二,副本集角色
- 主节点(Primary)
接收所有的写请求,然后把修改同步到所有Secondary。一个副本集只能有一个Primary节点,当Primary挂掉后,其他Secondary或者Arbiter节点会重新选举出来一个主节点。默认读请求也是发到Primary节点处理的,可以通过修改客户端连接配置以支持读取Secondary节点。 - 副本节点(Secondary)
与主节点保持同样的数据集。当主节点挂掉的时候,参与选主。 - 仲裁者(Arbiter)
不保有数据,不参与选主,只进行选主投票。使用Arbiter可以减轻数据存储的硬件需求,Arbiter几乎没什么大的硬件资源需求,但重要的一点是,在生产环境下它和其他数据节点不要部署在同一台机器上。
三,两种架构模式
- PSS
Primary + Secondary + Secondary模式,通过Primary和Secondary搭建的副本集
由一个主副本和两个从副本组成的3个成员副本集的关系图。
- PSA
Primary + Secondary + Arbiter模式,使用Arbiter搭建副本集
偶数个数据节点,加一个Arbiter构成的副本集
四,搭建MongoDB副本集
1.环境准备
- MongoDB版本:4.4.9
- 操作系统:centos8.2
- 副本集服务器:IP:10.0.0.56 port:27017 IP:10.0.0.57 port:27017 IP:10.0.0.58 port:27017
2.下载安装MongoDB
安装教程
这里是通过yum安装的,MongoDB默认数据路径在/var/lib/mongo,日志路径在/var/log/mongodb/mongod.log,配置文件路径在/etc/mongod.conf
3.为三台服务器配置文件添加副本集参数
# mongod.conf
# for documentation of all options, see:
# http://docs.mongodb.org/manual/reference/configuration-options/
# where to write logging data.
systemLog:
destination: file
logAppend: true
#数据库日志路径
path: /var/log/mongodb/mongod.log
# Where and how to store data.
storage:
#数据库存储路径
dbPath: /var/lib/mongo
journal:
enabled: true
# engine:
# wiredTiger:
# how the process runs
processManagement:
fork: true # fork and run in background
pidFilePath: /var/run/mongodb/mongod.pid # location of pidfile
timeZoneInfo: /usr/share/zoneinfo
# network interfaces
net:
port: 27017
#这里要开启远程访问 否则会报错
bindIp: 0.0.0.0 # Enter 0.0.0.0,:: to bind to all IPv4 and IPv6 addresses or, alternatively, use the net.bindIpAll setting.
#security:
#operationProfiling:
#replication:
#副本集参数
replication:
#副本集名称,每台服务器都要一样
replSetName: mongo_rep
#sharding:
## Enterprise-Only Options
#auditLog:
#snmp:
4.重启MongoDB,创建副本集,初始化副本集
修改完配置文件要重新加载配置文件:
systemctl restart mongod
进入 mongo 客户端创建副本集:
> config={_id:'mongo_rep',members:[
{_id:0,host:'10.0.0.56:27017'},
{_id:1,host:'10.0.0.57:27017'},
{_id:2,host:'10.0.0.58:27017'}]}
初始化副本集:
rs.initiate(config)
查看副本集状态:
rs.status()
#查看结果:
{
"set" : "mongo_rep",
"date" : ISODate("2021-10-18T05:53:52.182Z"),
"myState" : 1,
"term" : NumberLong(1),
"syncSourceHost" : "",
"syncSourceId" : -1,
"heartbeatIntervalMillis" : NumberLong(2000),
"majorityVoteCount" : 2,
"writeMajorityCount" : 2,
"votingMembersCount" : 3,
"writableVotingMembersCount" : 3,
"optimes" : {
"lastCommittedOpTime" : {
"ts" : Timestamp(1634536427, 1),
"t" : NumberLong(1)
},
"lastCommittedWallTime" : ISODate("2021-10-18T05:53:47.860Z"),
"readConcernMajorityOpTime" : {
"ts" : Timestamp(1634536427, 1),
"t" : NumberLong(1)
},
"readConcernMajorityWallTime" : ISODate("2021-10-18T05:53:47.860Z"),
"appliedOpTime" : {
"ts" : Timestamp(1634536427, 1),
"t" : NumberLong(1)
},
"durableOpTime" : {
"ts" : Timestamp(1634536427, 1),
"t" : NumberLong(1)
},
"lastAppliedWallTime" : ISODate("2021-10-18T05:53:47.860Z"),
"lastDurableWallTime" : ISODate("2021-10-18T05:53:47.860Z")
},
"lastStableRecoveryTimestamp" : Timestamp(1634536377, 4),
"electionCandidateMetrics" : {
"lastElectionReason" : "electionTimeout",
"lastElectionDate" : ISODate("2021-10-18T05:52:57.684Z"),
"electionTerm" : NumberLong(1),
"lastCommittedOpTimeAtElection" : {
"ts" : Timestamp(0, 0),
"t" : NumberLong(-1)
},
"lastSeenOpTimeAtElection" : {
"ts" : Timestamp(1634536367, 1),
"t" : NumberLong(-1)
},
"numVotesNeeded" : 2,
"priorityAtElection" : 1,
"electionTimeoutMillis" : NumberLong(10000),
"numCatchUpOps" : NumberLong(0),
"newTermStartDate" : ISODate("2021-10-18T05:52:57.841Z"),
"wMajorityWriteAvailabilityDate" : ISODate("2021-10-18T05:52:58.910Z")
},
"members" : [
{
"_id" : 0,
"name" : "10.0.0.56:27017",
"health" : 1,
"state" : 1,
"stateStr" : "PRIMARY",
"uptime" : 1847,
"optime" : {
"ts" : Timestamp(1634536427, 1),
"t" : NumberLong(1)
},
"optimeDate" : ISODate("2021-10-18T05:53:47Z"),
"syncSourceHost" : "",
"syncSourceId" : -1,
"infoMessage" : "",
"electionTime" : Timestamp(1634536377, 1),
"electionDate" : ISODate("2021-10-18T05:52:57Z"),
"configVersion" : 1,
"configTerm" : 1,
"self" : true,
"lastHeartbeatMessage" : ""
},
{
"_id" : 1,
"name" : "10.0.0.57:27017",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 64,
"optime" : {
"ts" : Timestamp(1634536427, 1),
"t" : NumberLong(1)
},
"optimeDurable" : {
"ts" : Timestamp(1634536427, 1),
"t" : NumberLong(1)
},
"optimeDate" : ISODate("2021-10-18T05:53:47Z"),
"optimeDurableDate" : ISODate("2021-10-18T05:53:47Z"),
"lastHeartbeat" : ISODate("2021-10-18T05:53:51.794Z"),
"lastHeartbeatRecv" : ISODate("2021-10-18T05:53:51.330Z"),
"pingMs" : NumberLong(0),
"lastHeartbeatMessage" : "",
"syncSourceHost" : "10.0.0.56:27017",
"syncSourceId" : 0,
"infoMessage" : "",
"configVersion" : 1,
"configTerm" : 1
},
{
"_id" : 2,
"name" : "10.0.0.58:27017",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 64,
"optime" : {
"ts" : Timestamp(1634536427, 1),
"t" : NumberLong(1)
},
"optimeDurable" : {
"ts" : Timestamp(1634536427, 1),
"t" : NumberLong(1)
},
"optimeDate" : ISODate("2021-10-18T05:53:47Z"),
"optimeDurableDate" : ISODate("2021-10-18T05:53:47Z"),
"lastHeartbeat" : ISODate("2021-10-18T05:53:51.794Z"),
"lastHeartbeatRecv" : ISODate("2021-10-18T05:53:51.345Z"),
"pingMs" : NumberLong(0),
"lastHeartbeatMessage" : "",
"syncSourceHost" : "10.0.0.56:27017",
"syncSourceId" : 0,
"infoMessage" : "",
"configVersion" : 1,
"configTerm" : 1
}
],
"ok" : 1,
"$clusterTime" : {
"clusterTime" : Timestamp(1634536427, 1),
"signature" : {
"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"keyId" : NumberLong(0)
}
},
"operationTime" : Timestamp(1634536427, 1)
}
5.测试
创建数据库插入数据:
use my_test
db.users.insert([{"username":"张三"},
{"username":"李四"},
{"username":"王五"},
{"username":"赵六"},
{"username":"老三"},])
查询数据库users集合中的文档:
db.users.find()
打开Secondary读的权限,查看数据是否同步:
rs.secondaryOk()
关闭Primary节点,查看Secondary是否重新选举为Primary