如何将 MongoDB 按计划备份到 DigitalOcean Spaces

介绍

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

文件系统级的备份包括在某个时刻拍摄底层数据文件,并允许数据库使用拍摄的文件中捕获的状态清洁恢复,它们对快速备份大型数据库具有重要作用,特别是当与文件系统拍摄相结合时,如 LVM 拍摄,或阻止存储量拍摄,如 DigitalOcean Block Storage Snapshots

逻辑备份包括使用工具(例如mongodumppg_dump)将数据从数据库导出到备份文件中,然后使用相应的恢复工具(例如mongorestorepg_restore)进行恢复。它们提供对何种数据进行备份和恢复的细微控制,并且备份通常可以在数据库版本和安装中移动。

设计一个有效的备份和恢复策略通常包括将性能影响、实施成本和数据存储成本与恢复速度、数据完整性和备份覆盖率进行交易,最佳解决方案将取决于您的恢复点和时间(https://en.wikipedia.org/wiki/Recovery_point_objective)以及数据库规模和架构。

在本指南中,我们将展示如何使用mongodump,一个内置的逻辑备份工具来备份MongoDB数据库,然后我们将展示如何将结果的序列化数据备份文件压缩和上传到DigitalOcean Spaces(https://andsky.com/tech/tutorials/an-introduction-to-digitalocean-spaces),一个高度冗余的对象存储。

到本教程结束时,您将实现可扩展的自动备份策略的框架,以便在您的应用程序遭受数据损失时快速恢复。对于较小的至中型数据库,使用mongodump的逻辑备份为您提供对哪些数据进行备份和恢复的精确控制。存储这些压缩备份档案在DigitalOcean Spaces中确保它们在可持续的对象存储中可用,以便您的应用程序数据在数据丢失事件发生时得到保护和快速恢复。

<$>[注] **注:**在使用mongodump工具时可能会产生一些性能影响,特别是在高负荷的数据库中。

前提条件

在您开始使用本指南之前,请确保您有以下前提条件:

一旦您登录到您的Droplet,启动和运行MongoDB,并创建了您的空间,您已经准备好开始。

步骤 1 - 输入测试数据

如果你从一个干净的 MongoDB 安装开始,还没有存储任何数据,你应该先将一些样本数据插入一个愚蠢的餐厅集合进行测试。

首先,使用 MongoDB 壳连接到运行数据库:

1mongo

您将看到以下Mongo壳提示:

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

默认情况下,壳连接到测试数据库。

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

1show collections

由于我们还没有将任何东西插入到数据库中,所以没有收藏,我们被带回了提示,没有输出。

让我们将文档插入一个愚蠢的餐厅收藏,它将自动创建(因为它还不存在):

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

你会看到以下的输出:

1[secondary_label Output]
2WriteResult({ "nInserted" : 1 })

这表明插入操作成功。

让我们再次列出收藏:

1show collections

现在我们看到我们新创建的餐厅收藏:

1[secondary_label Output]
2restaurants

要退出 MongoDB 壳,请按CTRL +D

现在我们已经在数据库中存储了一些样本数据,我们已经准备好备份它。

步骤 2 – 使用mongodump来备份 MongoDB 数据

我们现在将使用内置的mongodump实用程序来备份(或卸载)整个MongoDB数据库到一个压缩的档案文件。

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

1mkdir backup

现在,让我们将这个 MongoDB 实例中的测试数据库备份到一个被压缩的档案文件中,名为test_dump.gz。如果您的实例包含其他数据库,您可以在--db 旗帜之后替换另一个数据库名称为测试

<$>[注] **注:**下列命令应该从终端运行,而不是Mongo壳。

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

在这里,我们使用 - 档案标志来指定我们希望将所有数据保存到一个单一的档案文件中(其位置由档案参数指定),以及 - gzip标志来指定我们希望压缩此文件。

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

1[secondary_label Output]
22018-04-13T16:29:32.191+0000	writing test.restaurants to archive './backup/test_dump.gz'
32018-04-13T16:29:32.192+0000	done dumping test.restaurants (1 document)

这表明我们的测试数据已被成功卸载。

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

步骤 3 — 将备份档案上传到 DigitalOcean Spaces

要将此档案上传到我们的DigitalOcean Space,我们需要使用s3cmd工具,我们在前提条件(https://andsky.com/tech/tutorials/how-to-set-up-scheduled-mongodb-backups-to-digitalocean-spaces#prerequisites)中安装和配置。

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

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

你会看到以下的输出:

1[secondary_label Output]
2s3://mongo-backup-demo/ (bucket):
3   Location:  nyc3
4   Payer:     BucketOwner
5   Expiration Rule: none
6   Policy:    none
7   CORS:      none
8   ACL:       3587522: FULL_CONTROL

这表明连接成功,s3cmd可以将对象转移到太空。

让我们使用放置命令将我们在步骤 2 中创建的档案转移到我们的空间:

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

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

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

一旦转移完成,我们将通过列出空间内容来验证该文件已成功转移到我们的空间:

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

你应该看到备份档案文件:

1[secondary_label Output]
22018-04-13 20:39 297 s3://mongo-backup-demo/test_dump.gz

此时,您已成功备份测试 MongoDB 数据库并将备份档案转移到您的 DigitalOcean Space。

在下一节中,我们将讨论如何使用Bash来编写上面的程序,以便我们可以使用cron来编程。

第4步:创建并测试备份脚本

现在,我们已经将MongoDB数据库备份为压缩的档案文件,并将该文件转移到我们的空间,我们可以将这些手动步骤合并为一个单一的Bash脚本。

创建备份脚本

我们首先会编写一个组合mongodumps3cmd put命令的脚本,并添加一些额外的铃声和声,例如一些日志(使用响应

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

1nano backup_mongo.sh

插入以下代码片段,确保更新相关值以参考自己的空间,数据库和文件名称. 我们将称呼该文件为 'backup_mongo.sh',但您可以随心所欲命名此文件。

让我们通过这个脚本一部分:

1[label backup_mongo.sh]
2#!/bin/bash
3
4set -e
5...

在这里,‘#!/bin/bash’告诉壳解读脚本为Bash代码,‘set -e’告诉译者如果任何脚本命令失败,立即退出。

1[label backup_mongo.sh]
2...
3
4SPACE_NAME=mongo-backup-demo
5BACKUP_NAME=$(date +%y%m%d_%H%M%S).gz
6DB=test
7
8...

在本节中,我们设置了三种变量,我们将在以后使用:

  • SPACE_NAME:我们正在上传我们的备份文件的DigitalOcean空间的名称
  • BACKUP_NAME:备份档案的名称 在这里,我们将其设置为一个基本的日期时间字符串
  • DB:指定脚本将备份哪个MongoDB数据库。
 1[label backup_mongo.sh]
 2...
 3
 4date
 5echo "Backing up MongoDB database to DigitalOcean Space: $SPACE_NAME"
 6
 7echo "Dumping MongoDB $DB database to compressed archive"
 8mongodump --db $DB --archive=$HOME/backup/tmp_dump.gz --gzip
 9
10echo "Copying compressed archive to DigitalOcean Space: $SPACE_NAME"
11s3cmd put $HOME/backup/tmp_dump.gz s3://$SPACE_NAME/$BACKUP_NAME
12
13...

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

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

1[label backup_mongo.sh]
2...
3
4echo "Cleaning up compressed archive"
5rm $HOME/backup/tmp_dump.gz
6
7echo 'Backup complete!'

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

结合所有这些代码片段后,完整的脚本应该是这样的:

 1[label backup_mongo.sh]
 2#!/bin/bash
 3
 4set -e
 5
 6SPACE_NAME=mongo-backup-demo
 7BACKUP_NAME=$(date +%y%m%d_%H%M%S).gz
 8DB=test
 9
10date
11echo "Backing up MongoDB database to DigitalOcean Space: $SPACE_NAME"
12
13echo "Dumping MongoDB $DB database to compressed archive"
14mongodump --db $DB --archive=$HOME/backup/tmp_dump.gz --gzip
15
16echo "Copying compressed archive to DigitalOcean Space: $SPACE_NAME"
17s3cmd put $HOME/backup/tmp_dump.gz s3://$SPACE_NAME/$BACKUP_NAME
18
19echo "Cleaning up compressed archive"
20rm $HOME/backup/tmp_dump.gz
21
22echo 'Backup complete!'

请确保在完成后保存此文件。

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

备份脚本测试

让我们快速运行备份_mongo.sh脚本。

首先,使脚本可执行:

1chmod +x backup_mongo.sh

现在,运行脚本:

1./backup_mongo.sh

您将看到以下结果:

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

我们已经成功创建了一个备份壳脚本,现在可以使用cron来计划它。

步骤 5 – 使用 Cron 安排每日备份

为了在夜间运行备份脚本,我们将使用cron,这是一个内置于类似Unix的操作系统的任务安排工具。

首先,我们会创建一个目录来存储我们的备份脚本的日志,接下来,我们会将备份脚本添加到crontab(‘cron’的配置文件),所以‘cron’计划它在夜间运行。

创建一个Logging Directory

让我们创建一个目录来存储我们的备份脚本的日志文件. 这些日志将允许我们定期检查备份脚本,以确保一切顺利,如果某些命令失败,则调试。

/var/log中创建一个mongo_backup子目录(按照用于日志登录的惯例):

1sudo mkdir /var/log/mongo_backup

在这种情况下,我们的用户名是 sammy,但您应该为您的服务器使用相关的非根用户名,具有 sudo 特权。

1sudo chown sammy:sammy /var/log/mongo_backup

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

让我们创建日程安排的 cronjob。

创建Cronjob

要创建 cronjob,我们将编辑包含日程表任务列表的文件,称为crontab。 请注意,有多个crontabs,每个用户,一个系统的crontab在 /etc/crontab. 在本教程中,我们将运行备份脚本作为我们的用户 sammy;根据您的使用情况,您可以选择从系统的crontab运行。

打开 crontab 来编辑:

1crontab -e

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

 1[secondary_label Output]
 2no crontab for sammy - using an empty one
 3
 4Select an editor. To change later, run 'select-editor'.
 5  1. /bin/ed
 6  2. /bin/nano        <---- easiest
 7  3. /usr/bin/vim.basic
 8  4. /usr/bin/vim.tiny
 9
10Choose 1-4 [2]: no crontab for sammy - using an empty one

选择您喜爱的编辑器;选择nano,请输入2

1[label crontab -e]
2# For more information see the manual pages of crontab(5) and cron(8)
3#
4# m h dom mon dow command
5
60 2 * * * /home/sammy/backup_mongo.sh >>/var/log/mongo_backup/mongo_backup.log 2>&1

请确保在 crontab 的末尾包含一个追踪的新闻行. 保存并关闭文件。

你会看到以下的输出:

1[secondary_label Output]
2no crontab for sammy - using an empty one
3crontab: installing new crontab

备份脚本现在将每天早上2点运行。stdoutstderr(输出和错误流)都将被导出并附加到我们之前创建的日志目录中的名为mongo_backup.log的日志文件中。

您可以更改 0 2 * * * (在Cron语法中晚上2点执行) 到您想要的备份频率和时间。 有关Cron及其语法的更多信息,请参阅我们的教程 如何使用Cron来自动化VPS上的任务

我们将通过快速恢复练习结束本教程,以确保我们的备份功能。

步骤6 - 执行测试恢复

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

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

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

您将看到以下结果:

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

如果你用新鲜的 MongoDB 实例开始本教程,你会记得它只包含了测试数据库,这反过来就是我们备份的唯一数据库。

为了演示目的,我们现在将放下这个测试数据库,以便我们可以执行清洁恢复. 如果我们不执行这个第一步,恢复程序会遇到原始文档,它会跳过。

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

1mongo

现在,使用``测试数据库,然后从 MongoDB 实例中放下:

1use test
2db.dropDatabase()

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

1[secondary_label Output]
2{ "dropped" : "test", "ok" : 1 }

现在,离开mongo壳并执行mongorestore命令:

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

在这里,我们指定源备份文件是压缩和档案文件的形式(记住,我们在调用mongodump时使用了-档案-gzip旗帜),我们希望恢复到测试数据库。

您将看到以下结果:

1[secondary_label Output]
22018-04-16T23:10:07.317+0000	creating intents for archive
32018-04-16T23:10:07.453+0000	reading metadata for test.restaurants from archive 'test_dump.gz'
42018-04-16T23:10:07.497+0000	restoring test.restaurants from archive 'test_dump.gz'
52018-04-16T23:10:07.541+0000	restoring indexes for collection test.restaurants from metadata
62018-04-16T23:10:07.541+0000	finished restoring test.restaurants (1 document)
72018-04-16T23:10:07.541+0000	done

这表明测试恢复成功。

最后,让我们确认我们的初始餐厅数据已成功恢复。

打开 MongoDB 壳并查询餐厅收藏:

1db.restaurants.find()

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

1[secondary_label Output]
2{ "_id" : ObjectId("5ace7614dbdf8137afe60025"), "name" : "Pizzeria Sammy" }

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

结论

在本教程中,我们学会了如何实施和测试夜间逻辑MongoDB备份的策略。

此指南可以以多种方式扩展或修改,以下是一些快速建议:

  • 取决于您的恢复点目标(RPO),您可能希望增加或减少建议的备份频率以匹配您的数据恢复窗口
  • 另一个有用的添加将是一个警告函数,如果备份脚本子命令失败(例如,这个函数可能会发送电子邮件到定期监控的备份信箱)。
  • 此脚本不处理空间对象删除。

由于mongodump程序涉及快速读取所有被抛弃的数据,这种备份方法最适合小到中等大小的数据库,特别是用于特定集合或结果集等部分备份。 对于更大的部署,建议进行文件系统级备份。 有关文件系统级MongoDB备份的更多信息,请参阅本教程中的如何使用Dropplet Snapshots备份MongoDB(LINK0)。 有关备份MongoDB数据库的各种方法的更多信息,请参阅MongoDB手册(LINK1))。

本教程中的解决方案利用mongodump来对备份数据覆盖进行细微控制,以及DigitalOcean Spaces来实现成本效益且可持续的长期数据存储。 有关mongodump备份实用程序的更多信息,请参阅 MongoDB 手册中的 参考页面

Published At
Categories with 技术
comments powered by Disqus