mongoDB 的全量备份 思路 & 脚本

写在前面

今天心情好就写点东西,毕业也将近一年了,感觉生活 & 工作各个方面都还行,就是运动缺乏运动,所谓生命在于运动还是有道理的,不说废话了。我们直接进入主题吧。最进做了项目,用到了mongodDB数据库,关于mongoDB数据库,本文就不再介绍了,这里主要说一下mongoDB在阿里云上的全量备份方法。我们都是linux系统的菜鸟,对linux几乎一无所知的同学可以看一下,因为我在做备份之前,也是一脸蒙逼。下面我们来看一下吧。

备份思路

  1. 这次我们做的是全量备份,与mongoDB增量备份是不同的。相对来说,增量备份实现有些困难,之后有时间做增量备份吧! 全量备份顾名思义,就是全部备份,缺点就是每次备份都是将整个数据库都备份了。这样就很浪费内存,要知道线上机器的内存都是花钱买来的,但是为了数据安全,也就先这么着吧!
  2. 用过mongoDB都知道,在安装mongoDB数据库的时候,我们在对应的*./bin文件下面可以看到好多的.exe文件,这些工具就是 mongoDB 提供给用户管理数据库用的。今天我们主要用到了 mongodump.exe 这个工具,此工具就是用来备份数据库的,好处就是该工具在运行时,数据库依然可以正常写入和读取,有些时候我们备份数据库的时候,通常都是先锁定数据库防止写入,然后备份,备份好之后,再解锁。但是用了 mongoDB 自带的 mongodump.exe 我们可以放心的备份而不需要锁定数据库。
  3. 由于线上的机器肯定装了mongoDB数据库,所以我们今天的备份思路就是,在线上加定时任务,去执行一个 shell 脚本,然后再 shell 脚本中调用 mongoDB 自带的工具mongodump 备份数据库就好了,然后,我的设置是每天凌晨备份,保留最近 7天 的数据,7天 之前全部删掉,没必要保留。

开始备份

  1. 首先要知道,所有的shell脚本开头都应该这么写:

    1
    #!/bin/bash
  2. 头写好之后,下面我们需要指定几个变量:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    nameserver="127.0.0.1"
    user='test'
    password='123456789'
    commandpath='/usr/bin'
    targetpath='/tmp/backup'
    logpath='/usr'
    nowtime=$(date "+%Y%m%d%H:%M:%S" | cut -d ":" -f 1)
    dbname='cms'
    logtime=$(date "+%Y%m%d%H:%M:%S")
    removetime=$(date -d "-7 day" +"%Y%m%d%H")

    nameserver ————是服务器的 ip;
    user ————是数据库管理员的用户名;
    password ————自然就是密码了;
    targetpath ————数据库备份路径;
    logpath ————备份日志存储路径;
    nowtime ————当前时间,格式化输出,用作后面备份的数据库文件名称,方便删除和查看;
    dbname ————要备份的数据库的名称;
    logtime ————备份日志写入时间;
    removetime ————用户删除 7天之前 文件标识;

    这里需要注意一点,如果你给 mongoDB 数据库添加了管理员 ,那么我们在后面备份的时候必须指定 上面的 userpassword, 不然会报错,备份会不成功的。然而如果你没有设定管理员,那么后面备份的参数里面也不要写 userpassword 两个参数,否则也会出错,导致备份不成功。 ok ,here we go!

  3. 这里我会写两个用于运行的函数,start 函数用于备份数据, remove 函数用于删除旧的备份数据:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    start()
    {
    echo "[${logTime}]====backup start====" >> ${logpath}/mongodb-backup.log
    ${commandpath}/mongodump --host ${nameserver} -u ${user} -p ${password} --port 27017 -d ${dbname} --out ${targetpath}/${nowtime}
    }
    remove()
    {
    echo "[${logtime}]===removeold start===" >> ${logpath}/mongodb-backup.log
    if [ -d "${targetpath}/${removetime}/" ]
    then
    rm -rf "${targetpath}/${removetime}/"
    echo "===success:delete ${targetpath}/${removetime}/ completed!===" >> ${logpath}/mongodb-backup.log
    else
    echo "===failure:${targetpath}/${removetime}/ does not exists!===" >> ${logpath}/mongodb-backup.log
    fi
    echo "[${logtime}]===clear end ! ===" >> ${logpath}/mongodb-backup.log
    }

    这里也有值得注意的东西 就是必须指定备份日志的路径,不然会出现这样的问题,你备份成功了,但是日志没有记录下来,但是你在手动执行的是没有错误的,也备份成功了,日志也写入了。但是通过定时任务去执行 shell 脚本是,日志不能写入,即使你的数据备份成功了。所以这里要注意这一点。我已经踩过坑了。啊哈哈哈….. 而且我强烈建议路径一律用绝对路径,减少出错的机率。至于上面调用的 linux 命令不懂得,自行解决。

  4. 执行备份函数(start) 和 删除函数 (remove)进行备份和删除旧文件;

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    execute()
    {
    start
    if [ $? -eq 0 ]
    then
    echo "******backup successfully******" >> ${logpath}/mongodb-backup.log
    remove
    else
    echo "====backup failure====" >> ${logpath}/mongodb-backup.log
    fi
    }
    if [ ! -d "${targetpath}/${nowtime}/" ]
    then
    mkdir ${targetpath}/${nowtime}
    fi
    execute
    echo "[${logtime}]===******===backup end --> backup to the path: ${targetpath}/${nowtime} ===******===" >> ${logpath}/mongodb-backup.log

    这里需要需要说的也不多,if [ $? -eq 0 ] 这句代码的意思是判断上一个命令执行是否完成。 -eqlinux 中的 相等判断符号。 当 start 函数执行完成后,打印******backup successfully******标志,然后去删除旧备份数据的文件夹。 if [ ! -d "${targetpath}/${nowtime}/" ] 中的 -d 用于判断时候存在某一个文件夹。下面的代码应该都看得懂吧! 不需要多说了。经过实测,该备份方案完全可行,网友根据自己的实际情况做相应更改。ok, 基本到这里也说完了,下面奉上完整源代码。

完整源代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#!/bin/bash
# Description: use Linux Crontab create a task to backup Database for mongoDB
# Script Author: goooooog
#
# Variables
nameserver="127.0.0.1"
user='test'
password='123'
commandpath='/usr/bin'
targetpath='/tmp/backup'
logpath='/usr'
nowtime=$(date "+%Y%m%d%H:%M:%S" | cut -d ":" -f 1)
dbname='cms'
logtime=$(date "+%Y%m%d%H:%M:%S")
removetime=$(date -d "-7 day" +"%Y%m%d%H")
start()
{
echo "[${logTime}]====backup start====" >> ${logpath}/mongodb-backup.log
${commandpath}/mongodump --host ${nameserver} -u ${user} -p ${password} --port 27017 -d ${dbname} --out ${targetpath}/${nowtime}
}
remove()
{
echo "[${logtime}]===removeold start===" >> ${logpath}/mongodb-backup.log
if [ -d "${targetpath}/${removetime}/" ]
then
rm -rf "${targetpath}/${removetime}/"
echo "===success:delete ${targetpath}/${removetime}/ completed!===" >> ${logpath}/mongodb-backup.log
else
echo "===failure:${targetpath}/${removetime}/ does not exists!===" >> ${logpath}/mongodb-backup.log
fi
echo "[${logtime}]===clear end ! ===" >> ${logpath}/mongodb-backup.log
}
execute()
{
start
if [ $? -eq 0 ]
then
echo "******backup successfully******" >> ${logpath}/mongodb-backup.log
remove
else
echo "====backup failure====" >> ${logpath}/mongodb-backup.log
fi
}
if [ ! -d "${targetpath}/${nowtime}/" ]
then
mkdir ${targetpath}/${nowtime}
fi
execute
echo "[${logtime}]===******===backup end --> backup to the path: ${targetpath}/${nowtime} ===******===" >> ${logpath}/mongodb-backup.log

定时任务设置

首先你应该先登录到线上的机器,再进行一下的工作。

1
2
3
4
5
6
cd ..
cd etc
crontab -e #开始编辑定时任务
30 0 * * * 你的shell脚本放置的路径/backup.sh #注意绝对路径, 表示每天晚上12:30开始备份数据
crontab -l #查看所有的定时任务,确保你的定时任务已经加入

结束语

好吧,结束了,一个前端狗,用 linux 写的 shell 脚本备份 mongoDB 数据库的初体验就算完成了,有机会做增量备份。 欢迎指导。

Fork me on GitHub