作者介绍:老苏,10余年DBA工作运维经验,擅长Oracle、MySQL、PG、Mongodb数据库运维(如安装迁移,性能优化、故障应急处理等)
公众号:老苏畅谈运维
欢迎关注本人公众号,更多精彩与您分享。
一、项目背景
由于历史原因,生产环境中MongoDB使用的是单节点。但随着业务增长,考虑到这个同步业务的重要性,避免由于单节点故障造成业务停止,所以需要升级为副本集保证高可用。
下面这架构图是需要实现的MongoDB副本集高可用架构:
Relica Set副本集方式整体大概如图:
二、 升级架构前注意事项
在生产环境中,做单节点升级到集群前,一定要先备份好mongodb的所有数据,避免操作失误导致数据丢失。
并且在保证在升级期间不会有程序连接到MongoDB进行读写操作,建议停服务升级,且在凌晨业务低峰期,进行操作。
–使用mongodump进行全库备份
mongodump -uroot -p123456 --port 27017 --authenticationDatabase admin -j 2 -o /media/backup/full/$(date +%Y%m%d)
三、 原单节点MongoDB配置信息
角色 | IP |
---|---|
单节点 | IP:10.10.10.45 端口:27017 |
该节点配置信息:
# cat /etc/mongod.conf |grep -v '^#'
systemLog:
destination: file
logAppend: true
path: /var/log/mongodb/mongod.log
storage:
dbPath: /var/lib/mongo
journal:
enabled: true
processManagement:
timeZoneInfo: /usr/share/zoneinfo
net:
port: 27017
#bindIp: 127.0.0.1 # Enter 0.0.0.0,:: to bind to all IPv4 and IPv6 addresses or, alternatively, use the net.bindIpAll setting.
bindIp: 0.0.0.0
修改该配置文件增加副本集配置
# cat /etc/mongod.conf |grep -v '^#'
systemLog:
destination: file
logAppend: true
path: /var/log/mongodb/mongod.log
storage:
dbPath: /var/lib/mongo
journal:
enabled: true
processManagement:
timeZoneInfo: /usr/share/zoneinfo
net:
port: 27017
#bindIp: 127.0.0.1 # Enter 0.0.0.0,:: to bind to all IPv4 and IPv6 addresses or, alternatively, use the net.bindIpAll setting.
bindIp: 0.0.0.0
replication:
oplogSizeMB: 4096
replSetName: rs
四、新增节点信息
角色 | IP |
---|---|
新增从节点 | IP:10.10.10.46 端口:27017 |
新增仲裁节点 | IP:10.10.10.47 端口:27017 |
这两个节点配置文件,只需复制PRIMARY节点配置文件,并修改相应的 "bindIp"即可。
从节点配置:
# cat /etc/mongod.conf |grep -v '^#'
systemLog:
destination: file
logAppend: true
path: /var/log/mongodb/mongod.log
storage:
dbPath: /var/lib/mongo
journal:
enabled: true
processManagement:
timeZoneInfo: /usr/share/zoneinfo
net:
port: 27017
#bindIp: 127.0.0.1 # Enter 0.0.0.0,:: to bind to all IPv4 and IPv6 addresses or, alternatively, use the net.bindIpAll setting.
bindIp: 0.0.0.0
replication:
oplogSizeMB: 4096
replSetName: rs
仲裁节点配置:
# cat /etc/mongod.conf |grep -v '^#'
systemLog:
destination: file
logAppend: true
path: /var/log/mongodb/mongod.log
storage:
dbPath: /var/lib/mongo
journal:
enabled: true
processManagement:
timeZoneInfo: /usr/share/zoneinfo
net:
port: 27017
#bindIp: 127.0.0.1 # Enter 0.0.0.0,:: to bind to all IPv4 and IPv6 addresses or, alternatively, use the net.bindIpAll setting.
bindIp: 0.0.0.0
replication:
oplogSizeMB: 4096
replSetName: rs
启动3个节点:要先启动PRIMARY节点,2个SECONDARY节点后面启动。
# systemctl start mongod
五、 初始化副本集
使用mongo shell连接到主节点,执行初始化命令
test> use admin
switched to db admin
admin>
config = {
_id : "rs",
members : [
{_id:0, host:"10.10.10.45:27017"},
{_id:1, host:"10.10.10.46:27017"},
{_id:2, host:"10.10.10.47:27017", arbiterOnly: true},
]
}
> rs.initiate(config) //初始化副本集
{ ok: 1 } //返回ok:1成功,返回ok:0失败
• 查看集群状态信息
rs [direct: secondary] admin> rs.status()
{
set: 'rs',
date: ISODate('2024-07-06T08:56:17.985Z'),
myState: 1,
term: Long('1'),
syncSourceHost: '',
syncSourceId: -1,
heartbeatIntervalMillis: Long('2000'),
majorityVoteCount: 2,
writeMajorityCount: 2,
votingMembersCount: 3,
writableVotingMembersCount: 2,
optimes: {
lastCommittedOpTime: { ts: Timestamp({ t: 1720256169, i: 1 }), t: Long('1') },
lastCommittedWallTime: ISODate('2024-07-06T08:56:09.745Z'),
readConcernMajorityOpTime: { ts: Timestamp({ t: 1720256169, i: 1 }), t: Long('1') },
appliedOpTime: { ts: Timestamp({ t: 1720256169, i: 1 }), t: Long('1') },
durableOpTime: { ts: Timestamp({ t: 1720256169, i: 1 }), t: Long('1') },
lastAppliedWallTime: ISODate('2024-07-06T08:56:09.745Z'),
lastDurableWallTime: ISODate('2024-07-06T08:56:09.745Z')
},
lastStableRecoveryTimestamp: Timestamp({ t: 1720256159, i: 1 }),
electionCandidateMetrics: {
lastElectionReason: 'electionTimeout',
lastElectionDate: ISODate('2024-07-06T08:54:19.727Z'),
electionTerm: Long('1'),
lastCommittedOpTimeAtElection: { ts: Timestamp({ t: 1720256048, i: 1 }), t: Long('-1') },
lastSeenOpTimeAtElection: { ts: Timestamp({ t: 1720256048, i: 1 }), t: Long('-1') },
numVotesNeeded: 2,
priorityAtElection: 1,
electionTimeoutMillis: Long('10000'),
numCatchUpOps: Long('0'),
newTermStartDate: ISODate('2024-07-06T08:54:19.734Z'),
wMajorityWriteAvailabilityDate: ISODate('2024-07-06T08:54:20.619Z')
},
members: [
{
_id: 0,
name: '10.10.10.45:27017',
health: 1,
state: 1,
stateStr: 'PRIMARY',
uptime: 449,
optime: { ts: Timestamp({ t: 1720256169, i: 1 }), t: Long('1') },
optimeDate: ISODate('2024-07-06T08:56:09.000Z'),
lastAppliedWallTime: ISODate('2024-07-06T08:56:09.745Z'),
lastDurableWallTime: ISODate('2024-07-06T08:56:09.745Z'),
syncSourceHost: '',
syncSourceId: -1,
infoMessage: '',
electionTime: Timestamp({ t: 1720256059, i: 1 }),
electionDate: ISODate('2024-07-06T08:54:19.000Z'),
configVersion: 1,
configTerm: 1,
self: true,
lastHeartbeatMessage: ''
},
{
_id: 1,
name: '10.10.10.46:27017',
health: 1,
state: 2,
stateStr: 'SECONDARY',
uptime: 129,
optime: { ts: Timestamp({ t: 1720256169, i: 1 }), t: Long('1') },
optimeDurable: { ts: Timestamp({ t: 1720256169, i: 1 }), t: Long('1') },
optimeDate: ISODate('2024-07-06T08:56:09.000Z'),
optimeDurableDate: ISODate('2024-07-06T08:56:09.000Z'),
lastAppliedWallTime: ISODate('2024-07-06T08:56:09.745Z'),
lastDurableWallTime: ISODate('2024-07-06T08:56:09.745Z'),
lastHeartbeat: ISODate('2024-07-06T08:56:17.775Z'),
lastHeartbeatRecv: ISODate('2024-07-06T08:56:16.777Z'),
pingMs: Long('0'),
lastHeartbeatMessage: '',
syncSourceHost: '10.10.10.45:27017',
syncSourceId: 0,
infoMessage: '',
configVersion: 1,
configTerm: 1
},
{
_id: 2,
name: '10.10.10.47:27017',
health: 1,
state: 7,
stateStr: 'ARBITER',
uptime: 129,
lastHeartbeat: ISODate('2024-07-06T08:56:17.776Z'),
lastHeartbeatRecv: ISODate('2024-07-06T08:56:17.775Z'),
pingMs: Long('0'),
lastHeartbeatMessage: '',
syncSourceHost: '',
syncSourceId: -1,
infoMessage: '',
configVersion: 1,
configTerm: 1
}
],
ok: 1,
'$clusterTime': {
clusterTime: Timestamp({ t: 1720256169, i: 1 }),
signature: {
hash: Binary.createFromBase64('AAAAAAAAAAAAAAAAAAAAAAAAAAA=', 0),
keyId: Long('0')
}
},
operationTime: Timestamp({ t: 1720256169, i: 1 })
}
查看从库延时信息
rs [direct: primary] admin> rs.printSecondaryReplicationInfo()
source: 10.10.10.46:27017
{
syncedTo: 'Sat Jul 06 2024 16:57:29 GMT+0800 (China Standard Time)',
replLag: '0 secs (0 hrs) behind the primary '
}
上面看到从库已经完全同步,没有延时。
六、测试数据
–主库插入数据
rs [direct: primary] admin> for(i=0;i<1000;i++){db.log.insert({"uid":i,"name":"mongodb","age":6})};
DeprecationWarning: Collection.insert() is deprecated. Use insertOne, insertMany, or bulkWrite.
{
acknowledged: true,
insertedIds: { '0': ObjectId('6689087d597863336614a32f') }
}
rs [direct: primary] admin> show tables;
log
mycollection
system.keys
system.users
system.version
–从库上查看数据
rs [direct: secondary] admin> show tables;
log
mycollection
system.keys
system.users
system.version
rs [direct: secondary] admin> db.log.find().count()
1000
由此可以看出,主从节点数据同步正常。
关注我,学习更多数据库知识。