为什么要备份?
定期做数据库备份是防止数据意外丢失的关键部分。它们对于我们的业务正常运行非常重要。
下面,介绍各种备份策略以及优缺点以及其他的一些技巧。
通常,MongoDB 数据库备份分为两种:
- 逻辑备份
- 物理备份
此外,在使用逻辑备份时,我们还可以做增量备份,以捕获完全备份之间的增量或增量数据更改,以最大程度地减少发生灾难时的数据丢失量。
此外,还会介绍开源的备份工具 Percona Backup for MongoDB 。 pbm 能够在 MongoDB 中为副本集和分片集执行一致的备份。
逻辑备份
MongoDB 提供以下程序来进行逻辑备份:
Mongodump: 它可以从 MongoDB 数据库读取数据,并生成 BSON 文件
mongodump --host=mongodb1.example.net --port=27017 --username=user --authenticationDatabase=admin --db=demo --collection=events --out=/opt/backup/mongodump-2011-10-24
注意:如果没有指定数据库名称或集合名称,则会对整个数据库或集合进行备份。如果启用了 auth,那么我们必须指定 authenticationDatabase
另外,在备份仍在运行时,应使用 -oplog 获取增量数据,我们可以在 mongodump 中指定 -oplog 。请记住,仅适用于整个数据库备份。
mongodump --host=mongodb1.example.net --port=27017 --username=user --authenticationDatabase=admin --oplog --out=/opt/backup/mongodump-2011-10-24
优点:
- 它可以进行更细粒度级别的备份,例如特定的数据库或集合。
- 不需要暂停节点来进行备份,不影响业务
缺点:
- 由于它读取所有数据,因此速度可能很慢,并且对于大于 WT 缓存的 RAM 的数据库,也需要磁盘读取。WT 缓存压力增加会降低性能。
- mongodump 仅备份数据库中的文档,不备份索引,我们还原后,需要重新生成索引。
- 由于会产生大量的读写操作,备份的速度还取决于分配的 IOPS 和存储类型
- 逻辑备份(如 mongodump)在数据量大时需要很多时间
最佳实践提示:建议使用 secondary servers 服务器进行备份,以避免在 PRIMARY 节点上造成不必要的性能下降。
现在是处理逻辑备份时的还原部分。与备份相同,MongoDB 提供以下实用程序以进行还原。
Mongorestore:恢复由 mongodump 创建的备份文件。
mongorestore --host=mongodb1.example.net --port=27017 --username=user --password --authenticationDatabase=admin --db=demo --collection=events /opt/backup/mongodump-2011-10-24/events.bson
Percona Backup for MongoDB
它是一种分布式,低影响的解决方案,用于实现 MongoDB 分片集和副本集的一致备份。 Percona Backup for MongoDB 有助于在进行分片集备份时克服一致性的问题。 Percona Backup for MongoDB 在设计上是一个简单的命令行工具,非常适合备份较大的数据集。
启动 pbm 备份后,它会监控配置服务器副本集的所有分片,同时备份仍在运行,从而在备份完成后提供一致性。
除了具有启用 PITR 参数的完整数据库备份外,它还具有增量备份的功能。它通过在集群的 mongod 节点上运行 pbm-agent 来完成所有这些工作,并负责备份和还原。 如下所示, pbm list 命令在 Backup snapshots 部分显示完整的备份列表,在 PITR 部分显示增量备份。
以下是示例输出:
$ pbm list
Backup snapshots:
2020-09-10T12:19:10Z
2020-09-14T10:44:44Z
2020-09-14T14:26:20Z
2020-09-17T16:46:59Z
PITR <on>:
2020-09-14T14:26:40 - 2020-09-16T17:27:26
2020-09-17T16:47:20 - 2020-09-17T16:57:55
如果备份数据较大,则可以在 pbm-agent 日志中跟踪备份进度。让我们看看 pbm-agent 在进行备份时的输出。
Aug 19 08:46:51 ip-172-30-2-122 pbm -agent[24331]: 2020/08/19 08:46:51 Got command backup [{backup {2020-08-19T08:46:50Z s2} { } { 0} 1597826810}]
Aug 19 08:47:07 ip-172-30-2-122 pbm -agent[24331]: 2020/08/19 08:47:07 [INFO] backup/2020-08-19T08:46:50Z: backup started
Aug 19 08:47:09 ip-172-30-2-122 pbm -agent[24331]: 2020-08-19T08:47:09.891+0000 writing admin.system.users to archive on stdout
Aug 19 08:47:09 ip-172-30-2-122 pbm -agent[24331]: 2020-08-19T08:47:09.895+0000 done dumping admin.system.users (2 documents)
Aug 19 08:47:09 ip-172-30-2-122 pbm -agent[24331]: 2020-08-19T08:47:09.895+0000 writing admin.system.roles to archive on stdout
Aug 19 08:47:09 ip-172-30-2-122 pbm -agent[24331]: 2020-08-19T08:47:09.904+0000 done dumping admin.system.roles (1 document)
Aug 19 08:47:09 ip-172-30-2-122 pbm -agent[24331]: 2020-08-19T08:47:09.904+0000 writing admin.system.version to archive on stdout
Aug 19 08:47:09 ip-172-30-2-122 pbm -agent[24331]: 2020-08-19T08:47:09.914+0000 done dumping admin.system.version (5 documents)
Aug 19 08:47:09 ip-172-30-2-122 pbm -agent[24331]: 2020-08-19T08:47:09.914+0000 writing testmongo.col to archive on stdout
Aug 19 08:47:09 ip-172-30-2-122 pbm -agent[24331]: 2020-08-19T08:47:09.942+0000 writing test.collC to archive on stdout
Aug 19 08:47:13 ip-172-30-2-122 pbm -agent[24331]: 2020-08-19T08:47:13.499+0000 done dumping test.collC (1146923 documents)
Aug 19 08:47:13 ip-172-30-2-122 pbm -agent[24331]: 2020-08-19T08:47:13.500+0000 writing test.collA to archive on stdout
Aug 19 08:47:27 ip-172-30-2-122 pbm -agent[24331]: 2020-08-19T08:47:27.964+0000 done dumping test.collA (389616 documents)
Aug 19 08:47:27 ip-172-30-2-122 pbm -agent[24331]: 2020-08-19T08:47:27.965+0000 writing test.collG to archive on stdout
Aug 19 08:47:54 ip-172-30-2-122 pbm -agent[24331]: 2020-08-19T08:47:54.891+0000 done dumping testmongo.col (13280501 documents)
Aug 19 08:47:54 ip-172-30-2-122 pbm -agent[24331]: 2020-08-19T08:47:54.896+0000 writing test.collF to archive on stdout
Aug 19 08:48:09 ip-172-30-2-122 pbm -agent[24331]: 2020/08/19 08:48:09 [........................] test.collG 1533/195563 (0.8%)
Aug 19 08:48:09 ip-172-30-2-122 pbm -agent[24331]: 2020/08/19 08:48:09 [####################....] test.collF 116432/134747 (86.4%)
Aug 19 10:01:09 ip-172-30-2-122 pbm -agent[24331]: 2020/08/19 10:01:09 [#######################.] test.collG 195209/195563 (99.8%)
Aug 19 10:01:17 ip-172-30-2-122 pbm -agent[24331]: 2020/08/19 10:01:17 [########################] test.collG 195563/195563 (100.0%)
Aug 19 10:01:17 ip-172-30-2-122 pbm -agent[24331]: 2020-08-19T10:01:17.650+0000 done dumping test.collG (195563 documents)
Aug 19 10:01:20 ip-172-30-2-122 pbm -agent[24331]: 2020/08/19 10:01:20 [INFO] backup/2020-08-19T08:46:50Z: mongodump finished, waiting for the oplog
Aug 19 10:11:04 ip-172-30-2-122 pbm -agent[24331]: 2020/08/19 10:11:04 [INFO] backup/2020-08-19T08:46:50Z: backup finished
Aug 19 10:11:05 ip-172-30-2-122 pbm -agent[24331]: 2020/08/19 10:11:05 [INFO] pitr: streaming started from 2020-08-19 08:47:09 +0000 UTC / 1597826829
Aug 19 10:29:37 ip-172-30-2-122 pbm -agent[24331]: 2020/08/19 10:29:37 [INFO] pitr: created chunk 2020-08-19T08:47:09 - 2020-08-19T10:20:59. Next chunk creation scheduled to begin at ~2020-08-19T10:31:05
Aug 19 10:39:34 ip-172-30-2-122 pbm -agent[24331]: 2020/08/19 10:39:34 [INFO] pitr: created chunk 2020-08-19T10:20:59 - 2020-08-19T10:30:59. Next chunk creation scheduled to begin at ~2020-08-19T10:41:05
最后三行表示完整备份已完成
物理/文件系统备份
在某个时间点做快照或复制 MongoDB 数据文件 ,并允许使用快照文件中捕获的状态来恢复数据库。有助于快速备份大型数据库,尤其是在文件系统快照(例如 LVM 快照)或块存储卷快照相结合时。
有几种方法可以进行文件系统级备份,也称为物理备份。
- 手动复制整个数据文件(使用 Rsync →取决于 N/W 带宽)
- 基于 LVM 的快照
- 基于云的磁盘快照(AWS / GCP / Azure 或任何其他云提供商)
物理备份相对逻辑备份的优缺点。
优点:
- 通常比逻辑备份快。
- 可以轻松地复制到远程服务器或NAS
- 由于速度和可靠性,建议数据量大时使用
- 在同一集群或新集群中构建新节点时很方便
缺点:
- 无法进行较小级别的还原,例如特定的数据库或集合
- 尚未实现增量备份
以下是备份同一数据的时间对比:
数据库大小:267.6GB 索引大小:<1MB
demo:PRIMARY> db.runCommand({dbStats: 1, scale: 1024*1024*1024})
{
"db" : "test",
"collections" : 1,
"views" : 0,
"objects" : 137029,
"avgObjSize" : 2097192,
"dataSize" : 267.6398703530431,
"storageSize" : 13.073314666748047,
"numExtents" : 0,
"indexes" : 1,
"indexSize" : 0.0011749267578125,
"scaleFactor" : 1073741824,
"fsUsedSize" : 16.939781188964844,
"fsTotalSize" : 49.98826217651367,
"ok" : 1,
...
}
demo:PRIMARY>
- Percona Server for MongoDB’s Hot Backup:
语法:
> use admin
switched to db admin
> db.runCommand({createBackup: 1, backupDir: "/my/backup/data/path"})
{ "ok" : 1 }
最佳实践提示:备份路径 backupDir 应为绝对路径。它还支持将备份存储到文件系统和 AWS S3 存储中
[root@ip-172-31-37-92 tmp]# time mongo < hot.js
Percona Server for MongoDB shell version v4.2.8-8
connecting to: mongodb://127.0.0.1:27017/?compressors=disabled&gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("c9860482-7bae-4aae-b0e7-5d61f8547559") }
Percona Server for MongoDB server version: v4.2.8-8
switched to db admin
{
"ok" : 1,
...
}
bye
real 3m51.773s
user 0m0.067s
sys 0m0.026s
[root@ip-172-31-37-92 tmp]# ls
hot hot.js mongodb-27017.sock nohup.out systemd-private-b8f44077314a49899d0a31f99b31ed7a-chronyd.service-Qh7dpD tmux-0
[root@ip-172-31-37-92 tmp]# du -sch hot
15G hot
15G total
用了 4 分钟左右,在重建节点时,非常有用。
- 文件系统快照:
快照完成的大约时间只有 4 分钟。
[root@ip-172-31-37-92 ~]# aws ec2 describe-snapshots --query "sort_by(Snapshots, &StartTime)[-1].{SnapshotId:SnapshotId,StartTime:StartTime}"
{
"SnapshotId": "snap-0f4403bc0fa0f2e9c",
"StartTime": "2020-08-26T12:26:32.783Z"
}
[root@ip-172-31-37-92 ~]# aws ec2 describe-snapshots \
> --snapshot-ids snap-0f4403bc0fa0f2e9c
{
"Snapshots": [
{
"Description": "This is my snapshot backup",
"Encrypted": false,
"OwnerId": "021086068589",
"Progress": "100%",
"SnapshotId": "snap-0f4403bc0fa0f2e9c",
"StartTime": "2020-08-26T12:26:32.783Z",
"State": "completed",
"VolumeId": "vol-0def857c44080a556",
"VolumeSize": 50
}
]
}
3. Mongodump:
[root@ip-172-31-37-92 ~]# time nohup mongodump -d test -c collG -o /mongodump/ &
[1] 44298
?
[root@ip-172-31-37-92 ~]# sed -n '1p;$p' nohup.out
2020-08-26T12:36:20.842+0000 writing test.collG to /mongodump/test/collG.bson
2020-08-26T12:51:08.832+0000 [####....................] test.collG 27353/137029 (20.0%)
结果:从上面的例子可以看出,同样的数据量情况下,文件系统快照和 pbm 仅需 3~5 分钟,而 mongodump 花了约 15 分钟,只完成了 20% 的备份,速度太慢了。
结论
选择备份的最佳方法取决于多种因素,例如基础架构的类型,环境,可用资源,集群大小,负载等。
对于较小的实例,通过 mongodump 进行简单的逻辑备份就可以了。当达到大约 100G 以上的较大数据库大小时,请使用 Percona Backup for MongoDB 之类的备份方法,其中包括增量备份并抓取操作日志,以便能够执行针对特定时间点的恢复。
对于大型系统,也就是一旦达到 1TB + 范围,建议利用文件系统级快照备份。