目录
- 1. mongo单机安装
- 2. mongo(replica set)部署
- 3. mongodump 与 mongorestore工具使用
- 4.rsync工具使用
- 服务端配置
- 客户端配置
- 客户端推送与拉取文件
- 5. 完整mongo全量备份脚本
- 恢复全量备份数据
- 6. 完整mongo增量备份脚本(基于oplog)
- 恢复增量备份数据
- 7.备份策略
1. mongo单机安装
mongo版本:4.4.19
服务器版本:CentOS Linux release 7.9.2009
cd /etc/yum.repos.d/
touch mongodb-org-4.4.repo
[mongodb-org-4.4]
name=MongoDB Repository
baseurl=https://repo.mongodb.org/yum/redhat/$releasever/mongodb-org/4.4/x86_64/
gpgcheck=1
enabled=1
gpgkey=https://www.mongodb.org/static/pgp/server-4.4.asc
yum install -y mongodb-org
systemctl start mongod
卸载mongo:
1、在终端命令行中输入以下命令停止服务。
sudo service mongod stop
2、再输入命令删除软件包。
sudo yum erase $(rpm -qa | grep mongodb-org)
3、通过rm命令删除mongodb相关文件
sudo rm -r /var/log/mongodb
sudo rm -r /var/lib/mongo
2. mongo(replica set)部署
在三台机器按上述方法安装mongo:
192.168.91.12:27017
192.168.91.13:27017
192.168.91.14:27017
各个mongo节点修改mongo配置以副本集模式运行:
vim /etc/mongod.conf
replication:
replSetName: "rs0"
shell 登录mongo primary节点执行:
rs.initiate({
"_id": "rs0",
"members": [
{ "_id": 0, "host": "192.168.91.12:27017" },
{ "_id": 1, "host": "192.168.91.13:27017" },
{ "_id": 2, "host": "192.168.91.14:27017" }
]
});
执行后,12为primary节点, 13,14为secondary节点,
写入操作只能再primary节点,secondary节点不能进行写入操作,且会自动同步primary节点数据,若primary节点down机,secondary节点会自动选举出一个新的primary节点,此操作完全由mongo自动进行,不依赖三方插件。
副本集 移除节点命令:
rs.remove("192.168.91.13:27017");
rs.remove("192.168.91.14:27017");
3. mongodump 与 mongorestore工具使用
- mongodump的使用
备份整个数据库
sudo mongodump --db mydb --out /var/backups/mongo
–db 数据库名
–out 备份文件输出文件夹
备份单个表
mongodump -d mydb -o /var/backups/mongo --collection users
-d 数据库
-o 备份文件输出路径
–collection 指定的备份表
- mongorestore的使用
恢复整个数据库
sudo mongorestore --db mydb /var/backups/mongo/mydb
恢复单个集合
mongorestore -d mydb -c users mydb/users.bson
4.rsync工具使用
Linux下的远程数据同步工具,通过网络同步多台主机间的文件和目录。
安装:
yum install rsync -y
rsync运行模式:C/S
rsync监听端口:873
服务端配置
vim /etc/rsyncd.conf
uid = root
gid = root
port = 873
fake super = yes
use chroot = no
max connections = 200
timeout = 600
ignore errors
read only = false
list = false
auth users = rsync_backup
secrets file = /etc/rsync.passwd
pid file = /var/run/rsyncd.pid
address = 192.168.91.215
hosts allow = *
hosts deny = *
[backup]
comment = im rsync update dir
path = /data/backup
[mongodb_all_backup]
path = /data/backup/mongodb_all_backup
[mongodb_incr_backup]
path = /data/backup/mongodb_incr_backup
vim /etc/rsync.passwd
rsync_backup:yfk123456
systemctl restart rsyncd
客户端配置
vim /etc/rsync.pass
yfk123456
客户端推送与拉取文件
push
rsync -avz file.tar.gz rsync_backup@192.168.91.215::mongodb_all_backup/ --password-file=/etc/rsync.pass
命令参数解析:
rsync_backup: 服务端rsync用户名
192.168.91.215: 服务端地址
mongodb_all_backup/: 服务端创建文件模块
–password-file: 认证用户密码文件
pull
rsync -avz rsync_backup@192.168.91.215::mongodb_all_backup/ /data/ --password-file=/etc/rsync.pass
命令参数说明:
a#归档模式传输, 等于-tropgDl
-v #详细模式输出, 打印速率, 文件数量等
-z #传输时进行压缩以提高效率
-r #递归传输目录及子目录,即目录下得所有目录都同样传输。
-t #保持文件时间信息
-o #保持文件属主信息
-p #保持文件权限
-g #保持文件属组信息
-l#保留软连接
-P #显示同步的过程及传输时的进度等信息
-D #保持设备文件信息
-L #保留软连接指向的目标文件
-e#使用的信道协议,指定替代rsh的shell程序
--exclude=PATTERN #指定排除不需要传输的文件模式
--exclude-from=file #文件名所在的目录文件
--bwlimit=100#限速传输
--partial #断点续传
--delete #让目标目录和源目录数据保持一致
5. 完整mongo全量备份脚本
vim mongodb_all_back.sh
#!/bin/bash
#############################################################################
# 此脚本为 mongodb 的全量备份脚本,配合增量备份脚本一起使用 #
# 备份策略为:每周一次完全备份(0 4 * * 1),每天一次增量备份(30 3 * * *)。 #
#############################################################################
#推送备份服务器设置
backupServerHost='192.168.91.215'
backupModule='mongodb_all_backup'
backupUser='rsync_backup'
#客户端密码文件位置: /etc/rsync.pass chmod 600 /etc/rsync.pass
#mongo 数据库设置
host='192.168.91.12'
port='27017'
sourcepath=''
nowtime=$(date "+%Y%m%d")
#### 自动检查/创建增量备份路径 ####
if [ ! -d /data/mongodb_back/mongodb_backup_all/mongo-$port ];then
mkdir -p /data/mongodb_back/mongodb_backup_all/mongo-$port
fi
if [ ! -d /data/mongodb_back/mongodb_backup_all/log-$port ];then
mkdir -p /data/mongodb_back/mongodb_backup_all/log-$port
fi
targetpath="/data/mongodb_back/mongodb_backup_all/mongo-$port"
logpath="/data/mongodb_back/mongodb_backup_all/log-$port"
#### 备份函数 ####
start(){
mongodump --host $host --port $port --oplog --gzip --out ${targetpath}/${nowtime}
}
#### 判断备份是否成功的函数 ####
execute(){
echo "=========================$(date) backup all mongodb back start ${nowtime}=========" >> ${logpath}/${nowtime}.log
start
if [ $? -eq 0 ];then
echo "The MongoDB BackUp Successfully!" >> ${logpath}/${nowtime}.log
cd ${targetpath}
tar -zcvf "${nowtime}.tar.gz" ${nowtime}
echo "打包压缩完成 ${targetpath}/${nowtime}.tar.gz" >> ${logpath}/${nowtime}.log
#推送数据库备份文件 到备份服务器
echo "Message --传输数据库备份文件到备份服务器:" >> ${logpath}/${nowtime}.log
rsync -avz ${nowtime}.tar.gz ${backupUser}@${backupServerHost}::${backupModule}/ --password-file=/etc/rsync.pass >> ${logpath}/${nowtime}.log
#删除备份文件夹
rm -rf ${nowtime}/
else
echo "The MongoDB BackUp Failure" >> ${logpath}/${nowtime}.log
fi
}
execute
#### 删除7天前的备份 ####
backtime=$(date -d '-7 days' "+%Y%m%d")
if [ -f "${targetpath}/${backtime}.tar.gz" ];then
rm -rf "${targetpath}/${backtime}.tar.gz"
echo "=======${targetpath}/${backtime}/===删除完毕==" >> ${logpath}/${nowtime}.log
fi
echo "========================= $(date) backup all mongodb back end ${nowtime}=========" >> ${logpath}/${nowtime}.log
执行
sh /data/mongodb_back/script/mongodb_all_back.sh
输出:
数据库服务器:
备份后压缩包直接通过rsync发送到备份服务器:
全量备份数据文件位置:
/data/mongodb_back/mongodb_backup_all/mongo-27017
恢复全量备份数据
先登录mongo, 创建执行 mongorestore命令的专属权限用户root2:
use admin;
db.createRole(
{
role: "interalUseOnlyOplogRestore",
privileges: [
{ resource: { anyResource: true }, actions: [ "anyAction" ] }
],
roles: []
}
);
db.createUser({
user: "root2",
pwd: "123456",
roles: [
"interalUseOnlyOplogRestore"
]
});
执行命令:
先解压tar.gz
cd /data/mongodb_back/mongodb_backup_all/mongo-27017/20230227
tar zxvf 20230227.tar.gz
再执行恢复命令
mongorestore -h 127.0.0.1 -p 27017 --username root2 --password 123456 --oplogReplay --gzip /data/mongodb_back/mongodb_backup_all/mongo-27017/20230227
6. 完整mongo增量备份脚本(基于oplog)
oplog使用固定大小集合记录了数据库中所有修改操作的操作日志(新增、修改和删除,无查询),mongodb收到修改请求后,先在主节点(Primary)执行请求,再把操作日志保存到oplog表中,其他从节点(Secondary)到主节点拉取oplog并在异步进程中应用这些操作,从而达到主从数据的一致性。复制组内的所有节点都会保存一份oplog(集合名local.oplog.rs),这让他们可以保持同样的数据库状态。
mongodump 中的一个选项 --query 可以限制 mongodump 备份的内容, --oplogReplay 会在还原数据库转储后,还会从转储目录顶层中的 oplog.bson 文件中执行 oplog 条目。oplog 中又滚动记录这关于所有数据库写操作的日志。那么我们就可以通过备份 oplog 来实现增量备份。
通过限制oplog记录的 ts字段(时间戳),可达到秒级别的增量备份。
设置查询条件: 小于当前时间时间戳, 大于当前时间-1天时间戳可进行天级别的备份。
-query 参数:
{\"ts\":{\"\$gte\":{\"\$timestamp\": {\"t\": $ParamBakStartDate, \"i\": 1}},\"\$lte\":{\"\$timestamp\": {\"t\": $ParamBakEndDate, \"i\": 9999}}}}
由于shell脚本 $符号 和mongo的查询关键字 $gte冲突,所以将查询mongo查询语句输出到文件,通过
–queryFile参数查询
echo "{\"ts\":{\"\$gte\":{\"\$timestamp\": {\"t\": $ParamBakStartDate, \"i\": 1}},\"\$lte\":{\"\$timestamp\": {\"t\": $ParamBakEndDate, \"i\": 9999}}}}" > $bkdatapath/query.js
参考资料:MongoDB Developer Community
使用 db.printReplicationInfo() 查看oplog时间:
查询oplog记录:
use local;
db.oplog.rs.find();
db.oplog.rs.find({"ts":{"$gte":Timestamp(1677113401,1),"$lte":Timestamp(1677200401,9999)}});
oplog 数据格式:
{
"ts": Timestamp(1625660877, 2), // 日志的操作时间戳,第一个数字是时间戳,单位秒,第二个数字是当前秒的第2个操作
"t": NumberLong(2),
"h": NumberLong("5521980394145765083"),
"v": 2,
"op": "i", // i表示insert,u表示update,d表示delete,c 表示的是数据库的命令,比如建表,n表示noop,即空操作
"ns": "test.users", // 命名空间,即数据库和集合名称
"ui": UUID("edabbd93-76eb-42be-b54a-cdc29eb1f267"), // 连接到mongodb的客户端会话id
"wall": ISODate("2021-07-07T12:27:57.689Z"), // 操作执行时间,utc时间
"o": { // 操作的内容,对于不同的op类型,其格式不尽相同
"_id": ObjectId("60e59dcd46db1fb4605f8b18"),
"name": "1"
}
}
vim mongodb_incr_back.sh
#!/bin/bash
#############################################################################
# 此脚本为 mongodb 的增量备份脚本,配合完全备份脚本一起使用 #
# 备份策略为:每周一次完全备份(0 4 * * 1) 每周一凌晨4点,每天一次增量备份(30 3 * * *)。每天凌晨3点半 #
#############################################################################
# 每 10分钟执行一次 */10 * * * *
# 每 小时 执行一次 * */1 * * *
#
#推送备份服务器设置
backupServerHost='192.168.91.215'
backupModule='mongodb_incr_backup'
backupUser='rsync_backup'
#客户端密码文件位置: /etc/rsync.pass chmod 600 /etc/rsync.pass
#mongo服务器设置
command_linebin="mongo"
port="27017"
#### 自动检查/创建增量备份路径 ####
if [ ! -d "/data/mongodb_back/mongodboplog_back/mongo-$port" ];then
mkdir -p /data/mongodb_back/mongodb_oplog_back/mongo-$port
fi
if [ ! -d "/data/mongodb_back/mongodboplog_back/log-$port" ];then
mkdir -p /data/mongodb_back/mongodb_oplog_back/log-$port
fi
bkdatapath=/data/mongodb_back/mongodb_oplog_back/mongo-$port
bklogpath=/data/mongodb_back/mongodb_oplog_back/log-$port
#### 获取增量(oplog)备份的起止时间 ####、
#### 变量 DiffTime 为备份间隔,我这里是24小时+10分钟。多出来的10分钟是预估每次备份时间在10分钟以内,来确保数据的连续性 ####
logfilename=$(date -d today +"%Y%m%d")
echo "===================================Message --=MongoDB 端口为" $port "的差异备份开始,开始时间为" $(date -d today +"%Y-%m-%-d %H:%M:%S") >> $bklogpath/$logfilename.log
ParamBakEndDate=$(date +%s)
echo "Message --本次备份时间参数中的结束时间为:" $(date -d @$ParamBakEndDate +"%Y-%m-%-d %H:%M:%S")
echo "Message --本次备份时间参数中的结束时间为:" $(date -d @$ParamBakEndDate +"%Y-%m-%-d %H:%M:%S") >> $bklogpath/$logfilename.log
echo "Message --本次备份时间参数中的结束时间戳:" $ParamBakEndDate >> $bklogpath/$logfilename.log
#DiffTime=$(expr 65 \* 60)
DiffTime=$(echo "60*60*24 + 10*60" |bc)
echo "Message --备份设置的间隔时间为:" $DiffTime >> $bklogpath/$logfilename.log
ParamBakStartDate=$(expr $ParamBakEndDate - $DiffTime)
echo "Message --本次备份时间参数中的开始时间为:" $(date -d @$ParamBakStartDate +"%Y-%m-%-d %H:%M:%S")
echo "Message --本次备份时间参数中的开始时间为:" $(date -d @$ParamBakStartDate +"%Y-%m-%-d %H:%M:%S") >> $bklogpath/$logfilename.log
echo "Message --本次备份时间参数中的开始时间戳:" $ParamBakStartDate >> $bklogpath/$logfilename.log
####检查 oplog 中最早的一笔数据,验证此次备份的时间是否在 oplog 记录的时间范围内
bkfilename=$(date -d today +"%Y%m%d%H%M%S")
command_line="${command_linebin} localhost:$port"
opmes=$(/bin/echo "db.printReplicationInfo()" | $command_line --quiet)
echo $opmes > opdoctime$port.tmplog
opbktmplogfile=opdoctime$port.tmplog
opstartmes=$(grep "oplog first event time" $opbktmplogfile | awk -F 'CST' '{print $1}' | awk -F 'oplog first event time: ' '{print $2}' | awk -F ' GMT' '{print $1}' )
echo "Message --oplog集合记录的开始时间为:"$opstartmes >> $bklogpath/$logfilename.log
oplogRecordFirst=$(date -d "$opstartmes" +%s)
echo "Message --oplog集合记录的开始时间为:" $oplogRecordFirst >> $bklogpath/$logfilename.log
## 比较备份参数的开始时间是否在 oplog 记录的时间范围内
if [ $oplogRecordFirst -le $ParamBakStartDate ];then
echo "Message --检查设置备份时间合理。备份参数的开始时间在oplog记录的时间范围内。" >> $bklogpath/$logfilename.log
else
echo "Fatal Error --检查设置的备份时间不合理合理。备份参数的开始时间不在oplog记录的时间范围内。请调整oplog size或调整备份频率。本次备份可以持续进行,但还原时数据完整性丢失。" >> $bklogpath/$logfilename.log
fi
##echo "{\"ts\":{\"\$gte\":{\"\$timestamp\": {\"t\": $ParamBakStartDate, \"i\": 1}},\"\$lte\":{\"\$timestamp\": {\"t\": $ParamBakEndDate, \"i\": 9999}}}}"
echo "{\"ts\":{\"\$gte\":{\"\$timestamp\": {\"t\": $ParamBakStartDate, \"i\": 1}},\"\$lte\":{\"\$timestamp\": {\"t\": $ParamBakEndDate, \"i\": 9999}}}}"
echo "{\"ts\":{\"\$gte\":{\"\$timestamp\": {\"t\": $ParamBakStartDate, \"i\": 1}},\"\$lte\":{\"\$timestamp\": {\"t\": $ParamBakEndDate, \"i\": 9999}}}}" > $bkdatapath/query.js
##que=${ echo "{ts:{\$gte:Timestamp($ParamBakStartDate,1),\$lte:Timestamp($ParamBakEndDate,9999)}}" }
##echo $que
# 执行 mongodump
mongodump -h localhost --port $port -d local -c oplog.rs --queryFile $bkdatapath/query.js -o $bkdatapath/mongodboplog$bkfilename >> $bklogpath/$logfilename.log 2>&1
#### 再次检查,防止导出 oplog 数据时间过长,而导致旧数据被更新,所以再次进行检查 ####
#### 因 oplog 的空间大小是固定的,而且数据是滚动记录的。####
#### 如果在导出期间有大量的写操作,则 oplog 中新的数据会覆盖掉旧的数据,就可能导致导出的数据不完整,无法保证增量文件间的时间连续性。 ####
#DiffTime=$(expr 61 \* 60)
DiffTime=$(echo "60*60*24 + 5*60" |bc)
ParamAfterBakRequestStartDate=$(expr $ParamBakEndDate - $DiffTime)
echo "Message --为保证备份的连续性,本次备份后,oplog中的开始时间需小于:" $ParamAfterBakRequestStartDate >> $bklogpath/$logfilename.log
opmes=$(/bin/echo "db.printReplicationInfo()" | $command_line --quiet)
echo $opmes > opdoctime$port.tmplog
opbktmplogfile=opdoctime$port.tmplog
opstartmes=$(grep "oplog first event time" $opbktmplogfile | awk -F 'CST' '{print $1}' | awk -F 'oplog first event time: ' '{print $2}' | awk -F ' GMT' '{print $1}' )
echo "Message --执行备份后,oplog集合记录的开始时间为:"$opstartmes >> $bklogpath/$logfilename.log
oplogRecordFirst=$(date -d "$opstartmes" +%s)
echo "Message --执行备份后,oplog集合记录的开始时间为[时间格式化]:" $oplogRecordFirst >> $bklogpath/$logfilename.log
##begin 比较备份参数的开始时间是否在oplog记录的时间范围内
if [ $oplogRecordFirst -le $ParamAfterBakRequestStartDate ];then
echo "Message --备份后,检查 oplo g集合中数据的开始时间,即集合中最早的一笔数据,时间不小于$ParamAfterBakRequestStartDate。这样可以保证每个增量备份含有最近一个小时的全部 op 操作,满足数据的持续完整性,逐个还原无丢失数据风险。" >> $bklogpath/$logfilename.log
else
echo "Fatal Error --备份后,检查 oplog 集合的涵盖的时间范围过小。设置的备份时间不合理,备份后的文件不能完全涵盖最近1天的数据。请调整oplog size或调整备份频率。本次备份可以持续进行,但还原时数据完整性丢失。" >> $bklogpath/$logfilename.log
fi
#### 检查备份文件是否生成 ####
if [ -d "$bkdatapath/mongodboplog$bkfilename" ];then
echo "Message --检查此次备份文件已经产生.文件信息为:" $bkdatapath/mongodboplog$bkfilename >> $bklogpath/$logfilename.log
mv $bkdatapath/mongodboplog$bkfilename/local/oplog.rs.bson $bkdatapath/mongodboplog$bkfilename/local/oplog.bson
cd $bkdatapath
tar -zcvf mongodboplog$bkfilename.tar.gz mongodboplog$bkfilename
echo "Message --备份打包压缩完成" $bkdatapath/mongodboplog$bkfilename.tar.gz >> $bklogpath/$logfilename.log >> $bklogpath/$logfilename.log
#推送数据库备份文件到备份服务器
echo "Message --传输数据库备份文件到备份服务器:" >> $bklogpath/$logfilename.log
rsync -avz mongodboplog$bkfilename.tar.gz $backupUser@$backupServerHost::$backupModule/ --password-file=/etc/rsync.pass >> $bklogpath/$logfilename.log
#删除此备份文件夹
rm -rf mongodboplog$bkfilename/
else
echo "Fatal Error --备份过程已执行,但是未检测到备份产生的文件,请检查!" >> $bklogpath/$logfilename.log
fi
#### 删除历史备份文件,保留7天,如需调整,请在持续设置
keepbaktime=$(date -d '-7 days' "+%Y%m%d%H")*
if [ -f $bkdatapath/mongodboplog$keepbaktime.tar.gz ];then
rm -f $bkdatapath/mongodboplog$keepbaktime.tar.gz
echo "Message -- $bkdatapath/mongodboplog$keepbaktime 删除完毕" >> $bklogpath/$logfilename.log
fi
echo "============================Message --MongoDB 端口为" $port "的差异备份结束,结束时间为:" $(date -d today +"%Y%m%d%H%M%S") >> $bklogpath/$logfilename.log
执行: sh /data/mongodb_back/script/mongodb_incr_back.sh
恢复增量备份数据
先登录mongo, 创建执行 mongorestore命令的专属权限用户root2,同上述mongo全量备份,如已创建则不用创建
执行命令:
先解压tar.gz
cd /data/mongodb_back/mongodb_backup_all/mongo-27017/
tar zxvf mongodboplog20230223180002.tar.gz
再执行恢复命令
mongorestore -h 127.0.0.1 -p port --username root2 --password 123456 --oplogReplay /data/mongodb_back/mongodb_oplog_back/mongo-27017/mongodboplog20230223180002/local
7.备份策略
全量备份7天一次,并删除7天前的备份数据,备份时间:04:00
增量备份1天一次,拉取oplog数据为增量数据备份,并删除7天前的备份数据, 备份时间: 03:30
服务器添加定时任务:
crontab -e
0 4 * * 1 sh /data/mongodb_back/script/mongodb_all_back.sh
30 3 * * * sh /data/mongodb_back/script/mongodb_incr_back.sh
crontab -l 查看定时任务