如何设置到DigitalOceanSpaces的预定MongoDB备份

来自菜鸟教程
跳转至:导航、​搜索

介绍

定期数据库备份是防止意外数据丢失事件的关键步骤。 一般来说,有两大类备份:文件系统级(“物理”)备份和逻辑备份。

文件系统级备份涉及在某个时间点对底层数据文件进行快照,并允许数据库使用快照文件中捕获的状态进行干净的恢复。 它们有助于快速备份大型数据库,尤其是与文件系统快照(例如 LVM 快照)或块存储卷快照(例如 DigitalOcean Block Storage Snapshots)结合使用时。

逻辑备份涉及使用工具(例如 mongodumppg_dump)将数据从数据库导出到备份文件,然后使用相应的恢复工具(例如 mongorestorepg_restore)。 它们提供对要备份和恢复的数据的精细控制,并且备份通常可以跨数据库版本和安装进行移植。 由于逻辑备份工具读取通过内存备份的所有数据,它们可能会很慢,并且会为特别大的数据库造成不小的额外负载。

设计有效的备份和恢复策略通常涉及在性能影响、实施成本和数据存储成本与恢复速度、数据完整性和备份覆盖率之间进行权衡。 最佳解决方案将取决于您的恢复点和时间 目标 以及数据库规模和架构。

在本指南中,我们将演示如何使用内置的逻辑备份工具 mongodump 备份 MongoDB 数据库。 然后,我们将展示如何压缩生成的序列化数据备份文件并将其上传到 DigitalOcean Spaces,这是一个高度冗余的对象存储。 我们还将展示如何使用 Bash 和 cron 定期安排备份和上传操作,最后以示例数据恢复方案结束。

在本教程结束时,您将实现可扩展自动备份策略的框架,如果您的应用程序遭受数据丢失,您可以快速恢复。 对于中小型数据库,使用 mongodump 的逻辑备份可让您对要备份和恢复的数据进行细粒度控制。 将这些压缩备份存档存储在 DigitalOcean Spaces 中可确保它们在持久对象存储中随时可用,以便在发生数据丢失事件时保护您的应用程序数据并快速恢复。

注意: 使用 mongodump 工具时可能会有一些性能影响,尤其是在高负载的数据库上。 您应该首先使用具有模拟负载的非生产数据库测试此过程,以验证此方法是否适用于您的生产部署。


先决条件

在开始使用本指南之前,请确保您具备以下先决条件:

一旦您登录到您的 Droplet,启动并运行 MongoDB,并创建了您的空间,您就可以开始了。

第 1 步 — 插入测试数据

如果您从一个干净的 MongoDB 安装开始并且尚未存储任何数据,则应首先将一些示例数据插入一个虚拟 restaurants 集合以进行测试。 如果您的数据库中已经存储了一些集合和文档,请随意跳过此步骤并继续 步骤 2

首先,使用 MongoDB shell 连接到正在运行的数据库:

mongo

您将看到以下 Mongo shell 提示符:

MongoDB shell version: 3.2.19
connecting to: test
Welcome to the MongoDB shell.
For interactive help, type "help".
For more comprehensive documentation, see
    http://docs.mongodb.org/
Questions? Try the support group
    http://groups.google.com/group/mongodb-user
Server has startup warnings:
2018-04-11T20:30:57.320+0000 I CONTROL  [initandlisten]
2018-04-11T20:30:57.320+0000 I CONTROL  [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/defrag is 'always'.
2018-04-11T20:30:57.320+0000 I CONTROL  [initandlisten] **        We suggest setting it to 'never'
2018-04-11T20:30:57.320+0000 I CONTROL  [initandlisten]
>

默认情况下,shell 连接到 test 数据库。

让我们列出 test 数据库中存在的集合:

show collections

因为我们还没有向数据库中插入任何东西,所以没有集合,我们被带回到没有输出的提示。

让我们将一个文档插入到一个虚拟的 restaurants 集合中,它将自动创建(因为它还不存在):

db.restaurants.insert({'name': 'Pizzeria Sammy'})

您将看到以下输出:

OutputWriteResult({ "nInserted" : 1 })

这表明插入操作成功。

让我们再次列出集合:

show collections

我们现在看到我们新创建的 restaurants 集合:

Outputrestaurants

要退出 MongoDB shell,请按 CTRL + D

既然我们已经在数据库中存储了一些示例数据,我们就可以备份它了。

第 2 步 — 使用 mongodump 备份 MongoDB 数据

我们现在将使用内置的 mongodump 实用程序将整个 MongoDB 数据库备份(或“转储”)到压缩存档文件。

首先,让我们创建一个名为 backup 的临时目录来存储由 mongodump 创建的存档:

mkdir backup

现在,让我们将这个 MongoDB 实例中的 test 数据库备份到一个名为 test_dump.gz 的压缩存档文件中。 如果您的实例包含其他数据库,您可以在 --db 标志之后用另一个数据库名称替换 test。 您也可以省略 --db 标志来备份 MongoDB 实例中的 all 数据库。

注意:以下命令应该从终端运行,而不是 Mongo shell。


mongodump --db test --archive=./backup/test_dump.gz --gzip

在这里,我们使用 --archive 标志来指定我们希望将所有数据保存到单个存档文件(其位置由 archive 参数指定),并且 --gzip 标志来指定我们想要压缩这个文件。 此外,您可以选择使用 --collection--query 标志来选择给定的集合或查询进行归档。 要了解有关这些标志的更多信息,请参阅 mongodump 文档

运行转储命令后,您将看到以下输出:

Output2018-04-13T16:29:32.191+0000    writing test.restaurants to archive './backup/test_dump.gz'
2018-04-13T16:29:32.192+0000    done dumping test.restaurants (1 document)

这表明我们的测试数据已经成功转储。

在下一步中,我们将把这个备份存档上传到对象存储。

第 3 步 — 将备份存档上传到 DigitalOcean Spaces

要将此存档上传到我们的 DigitalOcean Space,我们需要使用 s3cmd 工具,该工具是我们在 Prerequisites 中安装和配置的。

我们将首先测试我们的 s3cmd 配置并尝试访问我们的备份空间。 在本教程中,我们将使用 mongo-backup-demo 作为我们的空间名称,但您应该填写您的空间的实际名称:

s3cmd info s3://mongo-backup-demo/

您将看到以下输出:

Outputs3://mongo-backup-demo/ (bucket):
   Location:  nyc3
   Payer:     BucketOwner
   Expiration Rule: none
   Policy:    none
   CORS:      none
   ACL:       3587522: FULL_CONTROL

表示连接成功,s3cmd可以将对象传送到空间。

让我们使用 put 命令将我们在步骤 2 中创建的存档传输到我们的空间:

s3cmd put ./backup/test_dump.gz s3://mongo-backup-demo/

你会看到一些文件传输输出:

Outputupload: './backup/test_dump.gz' -> 's3://mongo-backup-demo/test_dump.gz'  [1 of 1]
 297 of 297   100% in    0s    25.28 kB/s  done

传输完成后,我们将通过列出空间内容来验证文件是否已成功传输到我们的空间:

s3cmd ls s3://mongo-backup-demo/

您应该看到备份存档文件:

Output2018-04-13 20:39       297   s3://mongo-backup-demo/test_dump.gz

至此,您已成功备份 test MongoDB 数据库并将备份存档传输到您的 DigitalOcean Space。

在下一节中,我们将介绍如何使用 Bash 编写上述过程的脚本,以便我们可以使用 cron 来安排它。

第 4 步 — 创建和测试备份脚本

现在我们已经将 MongoDB 数据库备份到一个压缩存档文件并将这个文件传输到我们的 Space,我们可以将这些手动步骤组合到一个 Bash 脚本中。

创建备份脚本

我们将首先编写一个结合 mongodumps3cmd put 命令的脚本,并添加一些额外的花里胡哨,比如一些日志记录(使用 echos)。

在您喜欢的文本编辑器中打开一个空白文件(这里我们将使用 nano):

nano backup_mongo.sh

粘贴以下代码片段,确保更新相关值以引用您自己的空间、数据库和文件名。 我们将文件命名为 backup_mongo.sh,但您可以随意命名此文件。 您还可以在本节末尾找到完整的脚本。

让我们逐个浏览这个脚本:

backup_mongo.sh

#!/bin/bash

set -e
...

在这里,#!/bin/bash 告诉 shell 将脚本解释为 Bash 代码。 set -e 告诉解释器在任何脚本命令失败时立即退出。

backup_mongo.sh

...

SPACE_NAME=mongo-backup-demo
BACKUP_NAME=$(date +%y%m%d_%H%M%S).gz
DB=test

...

在本节中,我们将设置稍后将使用的三个变量:

  • SPACE_NAME:我们将备份文件上传到的 DigitalOcean 空间的名称
  • BACKUP_NAME:备份存档的名称。 在这里,我们将其设置为基本的日期时间字符串。
  • DB:指定脚本将备份的 MongoDB 数据库。 如果您要备份整个 MongoDB 实例(所有数据库),则不会使用此变量。

backup_mongo.sh

...

date
echo "Backing up MongoDB database to DigitalOcean Space: $SPACE_NAME"

echo "Dumping MongoDB $DB database to compressed archive"
mongodump --db $DB --archive=$HOME/backup/tmp_dump.gz --gzip

echo "Copying compressed archive to DigitalOcean Space: $SPACE_NAME"
s3cmd put $HOME/backup/tmp_dump.gz s3://$SPACE_NAME/$BACKUP_NAME

...

然后我们打印日期和时间(用于记录目的),并通过运行我们上面测试的 mongodump 命令开始备份。 我们再次将备份存档保存到 ~/backup/

接下来我们使用 s3cmd 将此存档复制到由这两个 SPACE_NAMEBACKUP_NAME 变量指定的位置。 例如,如果我们的空间名称为 mongo-backup-demo,当前日期和时间为 2018/04/12 12:42:21,则备份将命名为 180412_124221.gz 并保存到 mongo-backup-demo 空间。

backup_mongo.sh

...

echo "Cleaning up compressed archive"
rm $HOME/backup/tmp_dump.gz

echo 'Backup complete!'

在这里,我们从 ~/backup 目录中删除备份存档,因为我们已成功将其复制到我们的空间,最终输出指示备份已完成。

组合所有这些代码片段后,完整的脚本应如下所示:

backup_mongo.sh

#!/bin/bash

set -e

SPACE_NAME=mongo-backup-demo
BACKUP_NAME=$(date +%y%m%d_%H%M%S).gz
DB=test

date
echo "Backing up MongoDB database to DigitalOcean Space: $SPACE_NAME"

echo "Dumping MongoDB $DB database to compressed archive"
mongodump --db $DB --archive=$HOME/backup/tmp_dump.gz --gzip

echo "Copying compressed archive to DigitalOcean Space: $SPACE_NAME"
s3cmd put $HOME/backup/tmp_dump.gz s3://$SPACE_NAME/$BACKUP_NAME

echo "Cleaning up compressed archive"
rm $HOME/backup/tmp_dump.gz

echo 'Backup complete!'

完成后请务必保存此文件。

接下来,我们将测试此脚本以验证所有子命令是否有效。

测试备份脚本

让我们快速运行 backup_mongo.sh 脚本。

首先,使脚本可执行:

chmod +x backup_mongo.sh

现在,运行脚本:

./backup_mongo.sh

您将看到以下输出:

OutputMon Apr 16 22:20:26 UTC 2018
Backing up MongoDB database to DigitalOcean Space: mongo-backup-demo
Dumping MongoDB test database to compressed archive
2018-04-16T22:20:26.664+0000    writing test.restaurants to archive '/home/sammy/backup/tmp_dump.gz'
2018-04-16T22:20:26.671+0000    done dumping test.restaurants (1 document)
Copying compressed archive to DigitalOcean Space: mongo-backup-demo
upload: '/home/sammy/backup/tmp_dump.gz' -> 's3://mongo-backup-demo/180416_222026.gz'  [1 of 1]
 297 of 297   100% in    0s     3.47 kB/s  done
Cleaning up compressed archive
Backup complete!

我们已经成功创建了一个备份 shell 脚本,现在可以继续使用 cron 对其进行调度。

第 5 步 — 使用 Cron 安排每日备份

为了安排备份脚本的夜间运行,我们将使用 cron,这是一个内置于类 Unix 操作系统的作业调度实用程序。

首先,我们将创建一个目录来存储备份脚本的日志。 接下来,我们将备份脚本添加到 crontab(cron 的配置文件),以便 cron 安排它每晚运行。 由于 cron 支持任何常规频率,您可以选择安排每周或每月备份。

创建日志目录

让我们创建一个目录来存储我们的备份脚本的日志文件。 这些日志将允许我们定期检查备份脚本以确保一切正常,并在某些命令失败时进行调试。

/var/log 中创建一个 mongo_backup 子目录(按照用于记录的约定):

sudo mkdir /var/log/mongo_backup

现在,使该目录对我们的 Unix 用户可写。 在这种情况下,我们的用户名是 sammy,但您应该为您的服务器使用具有 sudo 权限的相关非 root 用户名。

sudo chown sammy:sammy /var/log/mongo_backup

我们的 Unix 用户 sammy 现在可以写入 /var/log/mongo_backup。 由于 cronjob 将作为 sammy 运行,它现在可以将其日志文件写入此目录。

让我们创建计划的 cronjob。

创建 Cronjob

要创建 cronjob,我们将编辑包含计划作业列表的文件,称为“crontab”。 请注意,有多个 crontab,每个用户一个,并且在 /etc/crontab 处有一个系统范围的 crontab。 在本教程中,我们将以用户 sammy 的身份运行备份脚本; 根据您的用例,您可以选择从系统范围的 crontab 运行它。

打开 crontab 进行编辑:

crontab -e

您将看到以下菜单,允许您选择首选的文本编辑器:

Outputno crontab for sammy - using an empty one

Select an editor.  To change later, run 'select-editor'.
  1. /bin/ed
  2. /bin/nano        <---- easiest
  3. /usr/bin/vim.basic
  4. /usr/bin/vim.tiny

Choose 1-4 [2]: no crontab for sammy - using an empty one

选择您喜欢的编辑器; 选择 nano 输入 2。 现在,将以下行附加到文件中,在注释掉的部分之后:

crontab -e

# For more information see the manual pages of crontab(5) and cron(8)
#
# m h  dom mon dow   command

0 2 * * * /home/sammy/backup_mongo.sh >>/var/log/mongo_backup/mongo_backup.log 2>&1

确保在 crontab 末尾包含一个尾随换行符。 保存并关闭文件。

您将看到以下输出:

Outputno crontab for sammy - using an empty one
crontab: installing new crontab

备份脚本现在将在每天凌晨 2:00 运行。 stdoutstderr(输出和错误流)都将通过管道传输并附加到我们之前创建的日志目录中名为 mongo_backup.log 的日志文件中。

您可以将 0 2 * * * (在 cron 语法中每晚凌晨 2:00 执行)更改为您想要的备份频率和时间。 要了解有关 cron 及其语法的更多信息,请参阅我们关于 如何使用 Cron 在 VPS 上自动执行任务的教程。

我们将通过快速恢复练习来结束本教程,以确保我们的备份正常工作。

第 6 步 — 执行测试恢复

任何备份策略都应该包含一个经过例行测试的恢复过程。 在这里,我们将快速测试从我们上传到 DigitalOcean 空间的压缩备份文件的恢复。

首先,我们将从 Space 下载 test_dump.gz 到 MongoDB Droplet 的主目录:

s3cmd get s3://mongo-backup-demo/test_dump.gz

您将看到以下输出:

Outputdownload: 's3://mongo-backup-demo/test_dump.gz' -> './test_dump.gz'  [1 of 1]
 297 of 297   100% in    0s  1305.79 B/s  done

如果您从一个新的 MongoDB 实例开始本教程,您会记得它只包含 test 数据库,而这又是我们备份的唯一数据库。

出于演示目的,我们现在将删除此测试数据库,以便我们可以执行干净的恢复。 如果我们不执行这第一步,恢复过程将遇到原始文档,它会跳过。 在您的特定用例中,仅恢复新文档可能是可以接受的,但出于本教程的目的,我们希望明确测试完全恢复到空数据库。

使用 mongo shell 连接到您的 MongoDB 实例:

mongo

现在,use test 数据库,并将其从 MongoDB 实例中删除:

use test
db.dropDatabase()

您将看到以下输出确认 test 下降:

Output{ "dropped" : "test", "ok" : 1 }

现在,退出 mongo shell 并执行 mongorestore 命令:

mongorestore --gzip --archive=test_dump.gz --db test

在这里,我们指定源备份文件被压缩并以“归档文件”形式(回想一下,我们在调用 mongodump 时使用了 --archive--gzip 标志),并且我们想恢复到 test 数据库。

您将看到以下输出:

Output2018-04-16T23:10:07.317+0000    creating intents for archive
2018-04-16T23:10:07.453+0000    reading metadata for test.restaurants from archive 'test_dump.gz'
2018-04-16T23:10:07.497+0000    restoring test.restaurants from archive 'test_dump.gz'
2018-04-16T23:10:07.541+0000    restoring indexes for collection test.restaurants from metadata
2018-04-16T23:10:07.541+0000    finished restoring test.restaurants (1 document)
2018-04-16T23:10:07.541+0000    done

这表示 test 恢复成功。

最后,让我们确认我们最初的restaurants数据已经成功恢复。

打开 MongoDB shell 并查询 restaurants 集合:

db.restaurants.find()

您应该会看到我们在本教程的第一步中保存的对象:

Output{ "_id" : ObjectId("5ace7614dbdf8137afe60025"), "name" : "Pizzeria Sammy" }

您现在已经成功实施并测试了这个 MongoDB 备份策略。

结论

在本教程中,我们学习了如何实现和测试每晚逻辑 MongoDB 备份的策略。

本指南可以通过多种方式进行扩展或修改。 以下是一些快速建议:

  • 根据您的恢复点目标 (RPO),您可能希望增加或减少建议的备份频率以匹配您的数据恢复窗口。
  • 另一个有用的添加是警报功能,如果备份脚本子命令失败(例如 此功能可以向定期监控的警报收件箱发送电子邮件)。
  • 此脚本不处理 Spaces 对象删除。 您可能希望清除 6 个月左右之前的备份。
  • 您可能想要实施更复杂的 备份轮换方案 ,具体取决于您的生产用例。

由于 mongodump 过程涉及快速读取所有转储数据,因此这种备份方法最适合中小型数据库,尤其适用于特定集合或结果集等部分备份。 对于较大的部署,建议使用文件系统级备份。 要了解有关文件系统级 MongoDB 备份的更多信息,请参阅本教程 如何使用 Droplet 快照备份 MongoDB 。 想要了解更多关于备份MongoDB数据库的各种方法,可以参考MongoDB手册

本教程中介绍的解决方案利用 mongodump 对备份数据覆盖范围进行精细控制,并利用 DigitalOcean Spaces 实现经济高效且持久的长期数据存储。 要了解有关 mongodump 备份实用程序的更多信息,请参阅 MongoDB 手册中的 参考页 。 要了解有关 DigitalOcean Spaces 的更多信息,您可以阅读 DigitalOcean Spaces 简介