Mongodb副本集
介绍
为了解决Mongodb数据高可用,官方提供了副本集机制,Mongodb副本集至少需要三个节点,其中一个是主节点,负责处理客户端请求,其余的都是从节点,负责复制主节点上的数据,两个从节点中也可以让其中一个节点做仲裁,不存数据。 Mongodb各个节点常见的搭配方式为:一主一从、一主多从。副本集中只有主能写,其余的从只能读。 主节点记录在其上的所有操作oplog,从节点定期轮询主节点获取这些操作,然后对自己的数据副本执行,这些操作,从而保证从节点的数据与主节点一致。
Mongodb副本集结构图如下所示:
当主节点发生故障后,其中一个从节点会成为新的主。
MongoDB副本集在主从复制基础上实现了故障转移的功能,也就是当主节点宕机时,某一台副本节点会自动提升为新主节点。
副本集搭建
搭建三台主机并安装mongodb 安装教程
1.定义PATH
vi /etc/profile.d/mongodb.sh ##增加或者修改
export PATH=$PATH:/usr/local/mongodb/bin
source /etc/profile.d/mongodb.sh ##使环境变量生效
2.创建keyfile (副本集各成员之间认证)
openssl rand -base64 20 > /usr/local/mongodb/conf/keyfile
chmod 400 /usr/local/mongodb/conf/keyfile
3.编辑配置文件
mkdir /usr/local/mongodb/{conf,logs}
mkdir -p /data/mongodb
vi /usr/local/mongodb/conf/mongodb.conf ##添加如下内容,注意有缩进
systemLog:
#MongoDB发送所有日志输出的目标指定为文件
destination: file
#mongod或mongos应向其发送所有诊断日志记录信息的日志文件的路径
path: "/usr/local/mongodb/logs/mongodb.log"
#当mongos或mongod实例重新启动时,mongos或mongod会将新条目附加到现有日志文件的末尾
logAppend: true
storage:
#mongod实例存储其数据的目录。storage.dbPath设置仅适用于mongod
dbPath: "/data/mongodb"
journal:
#启用或禁用持久性日志以确保数据文件保持有效和可恢复。
enabled: true
processManagement:
#启用在后台运行mongos或mongod进程的守护进程模式。
fork: true
#指定用于保存mongos或mongod进程的进程ID的文件位置,其中mongos或mongod将写入其PID
pidFilePath: "/usr/local/mongodb/logs/mongod.pid"
#从中加载时区数据库的完整路径
timeZoneInfo: /usr/share/zoneinfo
net:
#服务实例绑定所有IP,有副作用,副本集初始化的时候,节点名字会自动设置为本地域名,而不是ip
#bindIpAll: true
#服务实例绑定的IP,0.0.0.0让所有机器都能连接。
bindIp: 0.0.0.0
#bindIp
#绑定的端口
port: 27017
# 安全配置
security:
# 配置密码文件
keyFile: /usr/local/mongodb/conf/keyfile
replication:
#副本集的名称
replSetName: "aming"
4.编辑systemd服务管理脚本
vi /lib/systemd/system/mongodb.service ##写入如下内容
[Unit]
Description=mongodb
After=network.target remote-fs.target nss-lookup.target
[Service]
User=mongodb
Type=forking
ExecStart=/usr/local/mongodb/bin/mongod --config /usr/local/mongodb/conf/mongodb.conf
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -QUIT
PrivateTmp=true
[Install]
WantedBy=multi-user.target
5.创建用户,修改权限
useradd -s /sbin/nologin mongodb
chown -R mongodb /data/mongodb /usr/local/mongodb
6.启动服务
systemctl daemon-reload
systemctl start mongodb
systemctl enable mongodb
7.安装其余节点 将节点1上的mongodb相关文件拷贝到另外两个节点
scp -r /usr/local/mongodb aminglinux02:/usr/local/
scp -r /usr/local/mongodb aminglinux03:/usr/local/
scp /lib/systemd/system/mongodb.service aminglinux02:/lib/systemd/system/
scp /lib/systemd/system/mongodb.service aminglinux03:/lib/systemd/system/
其他操作同上
8.节点1上创建用户 编辑配置文件
vi /usr/local/mongodb/conf/mongodb.conf ##注释掉下面几行
# 安全配置
#security:
# 配置密码文件
#keyFile: /usr/local/mongodb/conf/keyfile
#replication:
#副本集的名称
#replSetName: "aming"
重启服务
systemctl restart mongodb
用mongosh工具连接mongodb 安装教程
mongosh ip:prot
进到mongodb命令行里面,创建用户
use admin
db.createUser({user:"root",pwd:"aminglinux.com",roles:["root"]})
退出mongodb命令行,继续编辑配置文件,将刚刚注释掉的几行恢复
vi /usr/local/mongodb/conf/mongodb.conf ##注释掉下面几行
# 安全配置
security:
# 配置密码文件
keyFile: /usr/local/mongodb/conf/keyfile
replication:
#副本集的名称
replSetName: "aming"
重启服务
systemctl restart mongodb
9.到节点1上初始化副本集
连接mongodb
mongosh ip:prot
认证
use admin
db.auth("root","aminglinux.com")
副本集初始化
rs.initiate(
{
_id: "aming",
version: 1,
members: [
{ _id: 0, host : "aminglinux01:27017" },
{ _id: 1, host : "aminglinux02:27017", arbiterOnly: true },
{ _id: 2, host : "aminglinux03:27017" }
]
}
)
查看副本集状态
aming [direct: primary] admin> rs.status()
{
set: 'aming',
date: ISODate("2022-10-04T13:27:38.429Z"),
myState: 1,
term: Long("1"),
syncSourceHost: '',
syncSourceId: -1,
heartbeatIntervalMillis: Long("2000"),
majorityVoteCount: 2,
writeMajorityCount: 2,
votingMembersCount: 3,
writableVotingMembersCount: 2,
optimes: {
lastCommittedOpTime: { ts: Timestamp({ t: 1664890054, i: 1 }), t: Long("1") },
lastCommittedWallTime: ISODate("2022-10-04T13:27:34.625Z"),
readConcernMajorityOpTime: { ts: Timestamp({ t: 1664890054, i: 1 }), t: Long("1") },
appliedOpTime: { ts: Timestamp({ t: 1664890054, i: 1 }), t: Long("1") },
durableOpTime: { ts: Timestamp({ t: 1664890054, i: 1 }), t: Long("1") },
lastAppliedWallTime: ISODate("2022-10-04T13:27:34.625Z"),
lastDurableWallTime: ISODate("2022-10-04T13:27:34.625Z")
},
lastStableRecoveryTimestamp: Timestamp({ t: 1664890004, i: 1 }),
electionCandidateMetrics: {
lastElectionReason: 'electionTimeout',
lastElectionDate: ISODate("2022-10-04T13:15:03.957Z"),
electionTerm: Long("1"),
lastCommittedOpTimeAtElection: { ts: Timestamp({ t: 1664889293, i: 1 }), t: Long("-1") },
lastSeenOpTimeAtElection: { ts: Timestamp({ t: 1664889293, i: 1 }), t: Long("-1") },
numVotesNeeded: 2,
priorityAtElection: 1,
electionTimeoutMillis: Long("10000"),
numCatchUpOps: Long("0"),
newTermStartDate: ISODate("2022-10-04T13:15:04.286Z"),
wMajorityWriteAvailabilityDate: ISODate("2022-10-04T13:15:05.828Z")
},
members: [
{
_id: 0,
name: 'aminglinux01:27017',
health: 1,
state: 1,
stateStr: 'PRIMARY',
uptime: 835,
optime: { ts: Timestamp({ t: 1664890054, i: 1 }), t: Long("1") },
optimeDate: ISODate("2022-10-04T13:27:34.000Z"),
lastAppliedWallTime: ISODate("2022-10-04T13:27:34.625Z"),
lastDurableWallTime: ISODate("2022-10-04T13:27:34.625Z"),
syncSourceHost: '',
syncSourceId: -1,
infoMessage: '',
electionTime: Timestamp({ t: 1664889303, i: 1 }),
electionDate: ISODate("2022-10-04T13:15:03.000Z"),
configVersion: 1,
configTerm: 1,
self: true,
lastHeartbeatMessage: ''
},
{
_id: 1,
name: 'aminglinux02:27017',
health: 1,
state: 7,
stateStr: 'ARBITER',
uptime: 764,
lastHeartbeat: ISODate("2022-10-04T13:27:38.120Z"),
lastHeartbeatRecv: ISODate("2022-10-04T13:27:37.485Z"),
pingMs: Long("2"),
lastHeartbeatMessage: '',
syncSourceHost: '',
syncSourceId: -1,
infoMessage: '',
configVersion: 1,
configTerm: 1
},
{
_id: 2,
name: 'aminglinux03:27017',
health: 1,
state: 2,
stateStr: 'SECONDARY',
uptime: 764,
optime: { ts: Timestamp({ t: 1664890054, i: 1 }), t: Long("1") },
optimeDurable: { ts: Timestamp({ t: 1664890054, i: 1 }), t: Long("1") },
optimeDate: ISODate("2022-10-04T13:27:34.000Z"),
optimeDurableDate: ISODate("2022-10-04T13:27:34.000Z"),
lastAppliedWallTime: ISODate("2022-10-04T13:27:34.625Z"),
lastDurableWallTime: ISODate("2022-10-04T13:27:34.625Z"),
lastHeartbeat: ISODate("2022-10-04T13:27:38.121Z"),
lastHeartbeatRecv: ISODate("2022-10-04T13:27:37.014Z"),
pingMs: Long("3"),
lastHeartbeatMessage: '',
syncSourceHost: 'aminglinux01:27017',
syncSourceId: 0,
infoMessage: '',
configVersion: 1,
configTerm: 1
}
],
ok: 1,
'$clusterTime': {
clusterTime: Timestamp({ t: 1664890054, i: 1 }),
signature: {
hash: Binary(Buffer.from("387cab53507429b2fa1e5de0d4bdef373f63e6f7", "hex"), 0),
keyId: Long("7150645112140201989")
}
},
operationTime: Timestamp({ t: 1664890054, i: 1 })
}
10.模拟故障 将节点1上的mongodb服务停掉
systemctl stop mongodb
到节点3上查看副本集状态
mongosh 127.0.0.1
use admin
db.auth("root","aminglinux.com")
rs.status()
{
set: 'aming',
date: ISODate("2022-10-09T08:13:37.403Z"),
myState: 1,
term: Long("3"),
syncSourceHost: '',
syncSourceId: -1,
heartbeatIntervalMillis: Long("2000"),
majorityVoteCount: 2,
writeMajorityCount: 2,
votingMembersCount: 3,
writableVotingMembersCount: 2,
optimes: {
lastCommittedOpTime: { ts: Timestamp({ t: 1665303208, i: 2 }), t: Long("3") },
lastCommittedWallTime: ISODate("2022-10-09T08:13:28.672Z"),
readConcernMajorityOpTime: { ts: Timestamp({ t: 1665303208, i: 2 }), t: Long("3") },
appliedOpTime: { ts: Timestamp({ t: 1665303208, i: 2 }), t: Long("3") },
durableOpTime: { ts: Timestamp({ t: 1665303208, i: 2 }), t: Long("3") },
lastAppliedWallTime: ISODate("2022-10-09T08:13:28.672Z"),
lastDurableWallTime: ISODate("2022-10-09T08:13:28.672Z")
},
lastStableRecoveryTimestamp: Timestamp({ t: 1664890404, i: 1 }),
electionCandidateMetrics: {
lastElectionReason: 'electionTimeout',
lastElectionDate: ISODate("2022-10-09T08:13:28.601Z"),
electionTerm: Long("3"),
lastCommittedOpTimeAtElection: { ts: Timestamp({ t: 1664890414, i: 1 }), t: Long("1") },
lastSeenOpTimeAtElection: { ts: Timestamp({ t: 1664890414, i: 1 }), t: Long("1") },
numVotesNeeded: 2,
priorityAtElection: 1,
electionTimeoutMillis: Long("10000"),
numCatchUpOps: Long("0"),
newTermStartDate: ISODate("2022-10-09T08:13:28.672Z"),
wMajorityWriteAvailabilityDate: ISODate("2022-10-09T08:13:29.698Z")
},
electionParticipantMetrics: {
votedForCandidate: true,
electionTerm: Long("1"),
lastVoteDate: ISODate("2022-10-09T07:56:09.459Z"),
electionCandidateMemberId: 0,
voteReason: '',
lastAppliedOpTimeAtElection: { ts: Timestamp({ t: 1664889293, i: 1 }), t: Long("-1") },
maxAppliedOpTimeInSet: { ts: Timestamp({ t: 1664889293, i: 1 }), t: Long("-1") },
priorityAtElection: 1
},
members: [
{
_id: 0,
name: 'aminglinux01:27017',
health: 0,
state: 8,
stateStr: '(not reachable/healthy)',
uptime: 0,
optime: { ts: Timestamp({ t: 0, i: 0 }), t: Long("-1") },
optimeDurable: { ts: Timestamp({ t: 0, i: 0 }), t: Long("-1") },
optimeDate: ISODate("1970-01-01T00:00:00.000Z"),
optimeDurableDate: ISODate("1970-01-01T00:00:00.000Z"),
lastAppliedWallTime: ISODate("2022-10-09T08:13:28.672Z"),
lastDurableWallTime: ISODate("2022-10-09T08:13:28.672Z"),
lastHeartbeat: ISODate("2022-10-09T08:13:36.815Z"),
lastHeartbeatRecv: ISODate("2022-10-09T08:13:29.686Z"),
pingMs: Long("1"),
lastHeartbeatMessage: 'Error connecting to aminglinux01:27017 (192.168.222.128:27017) :: caused by :: Connection refused',
syncSourceHost: '',
syncSourceId: -1,
infoMessage: '',
configVersion: 1,
configTerm: 1
},
{
_id: 1,
name: 'aminglinux02:27017',
health: 1,
state: 7,
stateStr: 'ARBITER',
uptime: 1057,
lastHeartbeat: ISODate("2022-10-09T08:13:36.702Z"),
lastHeartbeatRecv: ISODate("2022-10-09T08:13:36.701Z"),
pingMs: Long("2"),
lastHeartbeatMessage: '',
syncSourceHost: '',
syncSourceId: -1,
infoMessage: '',
configVersion: 1,
configTerm: 3
},
{
_id: 2,
name: 'aminglinux03:27017',
health: 1,
state: 1,
stateStr: 'PRIMARY',
uptime: 2384,
optime: { ts: Timestamp({ t: 1665303208, i: 2 }), t: Long("3") },
optimeDate: ISODate("2022-10-09T08:13:28.000Z"),
lastAppliedWallTime: ISODate("2022-10-09T08:13:28.672Z"),
lastDurableWallTime: ISODate("2022-10-09T08:13:28.672Z"),
syncSourceHost: '',
syncSourceId: -1,
infoMessage: '',
electionTime: Timestamp({ t: 1665303208, i: 1 }),
electionDate: ISODate("2022-10-09T08:13:28.000Z"),
configVersion: 1,
configTerm: 3,
self: true,
lastHeartbeatMessage: ''
}
],
ok: 1,
'$clusterTime': {
clusterTime: Timestamp({ t: 1665303208, i: 2 }),
signature: {
hash: Binary(Buffer.from("dd7df9ea0f127c3deb97a9658053320863968bcc", "hex"), 0),
keyId: Long("7150645112140201989")
}
},
operationTime: Timestamp({ t: 1665303208, i: 2 })
}
此时节点1,显示无法连接,节点3变成了primary
再次将节点1启动
systemctl start mongodb
节点3上再次查看副本集状态
rs.status()
{
set: 'aming',
date: ISODate("2022-10-09T08:15:29.956Z"),
myState: 1,
term: Long("3"),
syncSourceHost: '',
syncSourceId: -1,
heartbeatIntervalMillis: Long("2000"),
majorityVoteCount: 2,
writeMajorityCount: 2,
votingMembersCount: 3,
writableVotingMembersCount: 2,
optimes: {
lastCommittedOpTime: { ts: Timestamp({ t: 1665303328, i: 1 }), t: Long("3") },
lastCommittedWallTime: ISODate("2022-10-09T08:15:28.707Z"),
readConcernMajorityOpTime: { ts: Timestamp({ t: 1665303328, i: 1 }), t: Long("3") },
appliedOpTime: { ts: Timestamp({ t: 1665303328, i: 1 }), t: Long("3") },
durableOpTime: { ts: Timestamp({ t: 1665303328, i: 1 }), t: Long("3") },
lastAppliedWallTime: ISODate("2022-10-09T08:15:28.707Z"),
lastDurableWallTime: ISODate("2022-10-09T08:15:28.707Z")
},
lastStableRecoveryTimestamp: Timestamp({ t: 1665303208, i: 2 }),
electionCandidateMetrics: {
lastElectionReason: 'electionTimeout',
lastElectionDate: ISODate("2022-10-09T08:13:28.601Z"),
electionTerm: Long("3"),
lastCommittedOpTimeAtElection: { ts: Timestamp({ t: 1664890414, i: 1 }), t: Long("1") },
lastSeenOpTimeAtElection: { ts: Timestamp({ t: 1664890414, i: 1 }), t: Long("1") },
numVotesNeeded: 2,
priorityAtElection: 1,
electionTimeoutMillis: Long("10000"),
numCatchUpOps: Long("0"),
newTermStartDate: ISODate("2022-10-09T08:13:28.672Z"),
wMajorityWriteAvailabilityDate: ISODate("2022-10-09T08:13:29.698Z")
},
electionParticipantMetrics: {
votedForCandidate: true,
electionTerm: Long("1"),
lastVoteDate: ISODate("2022-10-09T07:56:09.459Z"),
electionCandidateMemberId: 0,
voteReason: '',
lastAppliedOpTimeAtElection: { ts: Timestamp({ t: 1664889293, i: 1 }), t: Long("-1") },
maxAppliedOpTimeInSet: { ts: Timestamp({ t: 1664889293, i: 1 }), t: Long("-1") },
priorityAtElection: 1
},
members: [
{
_id: 0,
name: 'aminglinux01:27017',
health: 1,
state: 2,
stateStr: 'SECONDARY',
uptime: 4,
optime: { ts: Timestamp({ t: 1665303328, i: 1 }), t: Long("3") },
optimeDurable: { ts: Timestamp({ t: 1665303328, i: 1 }), t: Long("3") },
optimeDate: ISODate("2022-10-09T08:15:28.000Z"),
optimeDurableDate: ISODate("2022-10-09T08:15:28.000Z"),
lastAppliedWallTime: ISODate("2022-10-09T08:15:28.707Z"),
lastDurableWallTime: ISODate("2022-10-09T08:15:28.707Z"),
lastHeartbeat: ISODate("2022-10-09T08:15:29.118Z"),
lastHeartbeatRecv: ISODate("2022-10-09T08:15:28.271Z"),
pingMs: Long("1"),
lastHeartbeatMessage: '',
syncSourceHost: 'aminglinux03:27017',
syncSourceId: 2,
infoMessage: '',
configVersion: 1,
configTerm: 3
},
{
_id: 1,
name: 'aminglinux02:27017',
health: 1,
state: 7,
stateStr: 'ARBITER',
uptime: 1169,
lastHeartbeat: ISODate("2022-10-09T08:15:28.843Z"),
lastHeartbeatRecv: ISODate("2022-10-09T08:15:28.828Z"),
pingMs: Long("1"),
lastHeartbeatMessage: '',
syncSourceHost: '',
syncSourceId: -1,
infoMessage: '',
configVersion: 1,
configTerm: 3
},
{
_id: 2,
name: 'aminglinux03:27017',
health: 1,
state: 1,
stateStr: 'PRIMARY',
uptime: 2496,
optime: { ts: Timestamp({ t: 1665303328, i: 1 }), t: Long("3") },
optimeDate: ISODate("2022-10-09T08:15:28.000Z"),
lastAppliedWallTime: ISODate("2022-10-09T08:15:28.707Z"),
lastDurableWallTime: ISODate("2022-10-09T08:15:28.707Z"),
syncSourceHost: '',
syncSourceId: -1,
infoMessage: '',
electionTime: Timestamp({ t: 1665303208, i: 1 }),
electionDate: ISODate("2022-10-09T08:13:28.000Z"),
configVersion: 1,
configTerm: 3,
self: true,
lastHeartbeatMessage: ''
}
],
ok: 1,
'$clusterTime': {
clusterTime: Timestamp({ t: 1665303328, i: 1 }),
signature: {
hash: Binary(Buffer.from("79f96888b9567f3f1be25b3436a206fc59c31519", "hex"), 0),
keyId: Long("7150645112140201989")
}
},
operationTime: Timestamp({ t: 1665303328, i: 1 })
}
节点1上线,变为secondary