mongo数据备份

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)部署

1.无密码副本集部署

在三台机器按上述方法安装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");

2.单机密码认证mongo改造单点Primary

openssl rand -base64 90 -out /etc/keyfile

chmod 400 /etc/keyfile
chown mongod /etc/keyfile

vim /etc/mongod.conf

security:
   authorization: enabled
   keyFile: /etc/keyfile

replication:
    replSetName: "rs0"

systemctl restart mongod
进入mongo shell:

use admin;
db.auth("root","pwd");

rs.initiate({
  "_id": "rs0",
  "members": [
    { "_id": 0, "host": "192.168.0.11:27017" }
  ]
})

3. mongodump 与 mongorestore工具使用

  1. mongodump的使用

备份所有库

sudo mongodump  --gzip --out /var/backups/mongo

备份整个数据库

sudo mongodump --db  mydb  --out /var/backups/mongo

–db 数据库名
–out 备份文件输出文件夹

备份单个表

mongodump -d mydb -o /var/backups/mongo --collection users

-d 数据库
-o 备份文件输出路径
–collection 指定的备份表

  1. mongorestore的使用

恢复所有数据库

mongorestore -h 127.0.0.1 -p 27017  --username root2 --password 123456    /data/backup/mongodb_all_backup/mongo

恢复整个数据库

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   --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 查看定时任务

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值