暂无图片
暂无图片
1
暂无图片
暂无图片
暂无图片

MongoDB 之 Percona backup for Mongo 测评

原创 大表哥 2023-02-22
3111

大家好,今天和大家分享的是 mongo DB 的一个备份工具 Percona backup for Mongo. 是由mysql 业界著名的公司Percona 开发的一款开源的备份工具。

熟悉mongo 的小伙伴都会知道, 社区版的mongo 不提供原生的增量备份的功能,只能用企业版的mongo 或者企业版 mongo ops manager 里面支持增量备份功能。

很多公司都使用的社区免费版的 mongo 或者 percona 版本的mongo , 并且把mongo 数据库作为海量数据的NOSQL数据库场景解决方案。 例如短消息, push notification, 用户行为追踪等等数据的存储。

每天的增量数据几个亿,增量几百个GB, 总量几个TB 的 mongo 实例也不在少数。 如果每天都用社区版提供的 mongodump 全备的话,从备份耗时到系统IO,以及备份空间的消耗都是不现实的。

当然了,业界不少公司也自己开发了基于oplog 实现的增量备份工具或者脚本。

对于一些没有足够资源去自研工具,但又想使用mongo 增量备份的公司来说,选择 Percona backup for Mongo 也许是一个不错的选择。

项目首页: https://www.percona.com/software/mongodb/percona-backup-for-mongodb

Image.png
就像首页上宣传的企业级的mongo 备份工具,100%开源, 以及下面的一些卖点:

Logical backups and restores
Physical (a.k.a. ‘hot’) backup and restore
Point-in-time recovery
Selective logical backups and restores
Works for both sharded clusters and non-sharded replica sets
Simple command-line management utility
Simple, integrated-with-MongoDB authentication
Distributed transaction consistency with MongoDB 4.2+
Can be used with any S3-compatible storage
Support for Microsoft Azure Blob storage
Supports filesystem storage type for locally mounted remote filesystem backup servers

我们下载一下这个工具,首页即可下载软件和用户手册(这个手册和mysql的xtrabackup 手册 如出一辙):

Image.png

解压备份工具:

INFRA [mongo@wqdcsrv3059 percona]# tar -xvf percona-backup-mongodb-2.0.3-x86_64.tar.gz percona-backup-mongodb-2.0.3/ percona-backup-mongodb-2.0.3/pbm percona-backup-mongodb-2.0.3/pbm-agent percona-backup-mongodb-2.0.3/pbm-speed-test percona-backup-mongodb-2.0.3/pbm-agent-entrypoint

我们查看一下PBM的版本: 2.0.3 , 这个工具的开发语言貌似是 golang.

INFRA [mongo@wqdcsrv3059 percona-backup-mongodb-2.0.3]# ./pbm version Version: 2.0.3 Platform: linux/amd64 GitCommit: 594eeb110d86939087858711b4f70b384a347758 GitBranch: release-2.0.3 BuildTime: 2023-01-11_14:14_UTC GoVersion: go1.19

安装完成之后,我们需要配置一下PBM, 下图是整体的PBM的架构:

Image.png

a)配置备份的账户

这个账户需要在所有备份的mongo 实例里面创建。 我们的mongo 版本是 Percona MongoDB server version: 4.2.22-22 ,架构是3节点的复制集.

MongoCapp24004:PRIMARY> db.getSiblingDB("admin").createRole({ "role": "pbmAnyAction", ... "privileges": [ ... { "resource": { "anyResource": true }, ... "actions": [ "anyAction" ] ... } ... ], ... "roles": [] ... }); { "role" : "pbmAnyAction", "privileges" : [ { "resource" : { "anyResource" : true }, "actions" : [ "anyAction" ] } ], "roles" : [ ] } MongoCapp24004:PRIMARY> db.getSiblingDB("admin").createUser({user: "pbmuser", ... "pwd": "secretpwd", ... "roles" : [ ... { "db" : "admin", "role" : "readWrite", "collection": "" }, ... { "db" : "admin", "role" : "backup" }, ... { "db" : "admin", "role" : "clusterMonitor" }, ... { "db" : "admin", "role" : "restore" }, ... { "db" : "admin", "role" : "pbmAnyAction" } ... ] ... }); Successfully added user: { "user" : "pbmuser", "roles" : [ { "db" : "admin", "role" : "readWrite", "collection" : "" }, { "db" : "admin", "role" : "backup" }, { "db" : "admin", "role" : "clusterMonitor" }, { "db" : "admin", "role" : "restore" }, { "db" : "admin", "role" : "pbmAnyAction" } ] }

2)配置PBM的环境变量 PBM_MONGODB_URI

INFRA [mongo@wqdcsrv3059 ~]# vi .bash_profile export PBM_MONGODB_URI="mongodb://pbmuser:secretpwd@127.0.0.1:24004/?authSource=admin"

3)配置备份的存储空间: 这个存储空间既可以是 AWS ,Azure 云上的,也可以是你本地的存储空间
我们测试配置本地的file system , 我们需要创建一个 yum 文件 : pbm_config.yaml

storage: type: filesystem filesystem: path: /data/local_backups
INFRA [mongo@wqdcsrv3059 ~]# /opt/percona/percona-backup-mongodb-2.0.3/pbm config --file pbm_config.yaml pitr: enabled: false oplogSpanMin: 0 compression: s2 storage: type: filesystem filesystem: path: /data/local_backups

4)启动 pbm-agent 进程

INFRA [mongo@wqdcsrv3059 ~]# nohup /opt/percona/percona-backup-mongodb-2.0.3/pbm-agent --mongodb-uri "mongodb://pbmuser:secretpwd@10.67.200.33:24004/?authSource=admin" > /data/local_backups/mongo_backup.log 2>&1 & [1] 111674

查看启动日志:

INFRA [mongo@wqdcsrv3059 ~]# tail -f /data/local_backups/mongo_backup.log Version: 2.0.3 Platform: linux/amd64 GitCommit: 594eeb110d86939087858711b4f70b384a347758 GitBranch: release-2.0.3 BuildTime: 2023-01-11_14:15_UTC GoVersion: go1.19 2023-02-20T11:26:08.000+0800 I starting PITR routine 2023-02-20T11:26:08.000+0800 I node: MongoCapp24004/10.67.200.33:24004 2023-02-20T11:26:08.000+0800 I listening for the commands 2023-02-20T11:26:13.000+0800 W [agentCheckup] get current storage status: query mongo: mongo: no documents in result

配置完毕之后,我们测试进行一个物理全备:pbm backup -t physical

INFRA [mongo@wqdcsrv3059 ~]# /opt/percona/percona-backup-mongodb-2.0.3/pbm backup -t physical Starting backup '2023-02-20T05:59:23Z'... Backup '2023-02-20T05:59:23Z' to remote store '/data/local_backups' has started

物理全备之后,我们看一下物理空间的占用大小是23GB, 实例的数据文件是25GB , 基本上是一致的

为什么有2GB的差距的原因是: 备份默认用的是 S2的压缩方式, 而mongo 本事的collection 本身就是 bson的 压缩格式,所以相差并不大

备份空间占用大小: 23GB

INFRA [mongo@wqdcsrv3059 2023-02-20T05:59:23Z]# du -h ./ --max-depth=1 23G ./MongoCapp24004 23G ./

实例空间大小: 25GB

INFRA [mongo@wqdcsrv3059 mongo24004]# du -h ./ --max-depth=1 25G ./dbdata 4.0K ./pid 4.0K ./keyfile 25G ./

下面我们采用–compression=gzip 的方式再次备份一下:

INFRA [mongo@wqdcsrv3059 dbdata]# /opt/percona/percona-backup-mongodb-2.0.3/pbm backup -t physical --compression=gzip

备份的空间空间减小到了18GB: 但是耗费的总时间从之前的 1分钟 上升到了 16分钟 , 这个对比结果还是有点惊人的

INFRA [mongo@wqdcsrv3059 2023-02-20T06:17:36Z]# du -h ./ --max-depth=1 18G ./MongoCapp24004 18G ./

我们下面进行一个逻辑备份: 需要在备份的命令中指定 pbm backup -t logical

INFRA [mongo@wqdcsrv3059 local_backups]# /opt/percona/percona-backup-mongodb-2.0.3/pbm backup -t logical Starting backup '2023-02-20T06:50:08Z'.... Backup '2023-02-20T06:50:08Z' to remote store '/data/local_backups' has started

我们看一下逻辑备份的大小: 4.2 GB 比之前的物理备份小了很多,
想必原因也是很简单的物理备份是直接拷贝文件,逻辑备份是类似于 mongodump 只导出数据(index 只是 metadata的语句信息), 可以去除集合中的碎片.

INFRA [mongo@wqdcsrv3059 2023-02-20T06:50:08Z]# du -h ./ --max-depth=1 4.2G ./MongoCapp24004 4.2G ./

接下来,我们要进行一个增量的备份, 目前PBM 这个工具 只有逻辑备份支持 增量的形式。(物理备份暂不支持)

INFRA [mongo@wqdcsrv3059 local_backups]# /opt/percona/percona-backup-mongodb-2.0.3/pbm backup --type=incremental --base Starting backup '2023-02-20T08:26:04Z'.... Backup '2023-02-20T08:26:04Z' to remote store '/data/local_backups' has started

我们查看一下,我们之前所有的备份集: 2个物理备份,1个逻辑备份,1个增减备份:

INFRA [mongo@wqdcsrv3059 local_backups]# /opt/percona/percona-backup-mongodb-2.0.3/pbm list Backup snapshots: 2023-02-20T05:59:23Z <physical> [restore_to_time: 2023-02-20T05:59:25Z] 2023-02-20T06:17:36Z <physical> [restore_to_time: 2023-02-20T06:17:39Z] 2023-02-20T06:50:08Z <logical> [restore_to_time: 2023-02-20T06:50:33Z] 2023-02-20T08:26:04Z <incremental> [restore_to_time: 2023-02-20T08:26:06Z] PITR <off>:

接下来,我们测试一下 point in time 的 recovery(基于时间点的恢复):

测试步骤如下:

前提条件: 打开 pitr.enabled=true 这个选项: 打开这个参数的意义是 周期性的备份 oplog , 默认是10分钟扫描一次 oplog

INFRA [mongo@wqdcsrv3059 local_backups]# /opt/percona/percona-backup-mongodb-2.0.3/pbm config --set pitr.enabled=true [pitr.enabled=true]

a) Logical 逻辑全备

INFRA [mongo@wqdcsrv3059 local_backups]# /opt/percona/percona-backup-mongodb-2.0.3/pbm backup -t logical Starting backup '2023-02-21T07:17:36Z'... Backup '2023-02-21T07:17:36Z' to remote store '/data/local_backups' has started INFRA [mongo@wqdcsrv3059 local_backups]# /opt/percona/percona-backup-mongodb-2.0.3/pbm list Backup snapshots: 2023-02-21T02:17:22Z <logical> [restore_to_time: 2023-02-21T02:17:43Z] 2023-02-21T07:17:36Z <logical> [restore_to_time: 2023-02-21T07:18:02Z] PITR <on>: 2023-02-21T02:17:44Z - 2023-02-21T07:18:02Z

b) 创建一个新的数据库 db_rpti_test, 插入测试数据

MongoCapp24004:PRIMARY> use db_rpti_test switched to db db_rpti_test MongoCapp24004:PRIMARY> db.coll_rpti_test.insert({"name":"目标恢复时间点"}); WriteResult({ "nInserted" : 1 })

c)记录目标恢复时间点:

MongoCapp24004:PRIMARY> print(Date()); Tue Feb 21 2023 15:20:00 GMT+0800 (CST)

测试插入一些数据:

MongoCapp24004:PRIMARY> db.coll_rpti_test.insert({"name":"testing 1"}); WriteResult({ "nInserted" : 1 }) MongoCapp24004:PRIMARY> db.coll_rpti_test.insert({"name":"testing 2"}); WriteResult({ "nInserted" : 1 }) MongoCapp24004:PRIMARY> db.coll_rpti_test.insert({"name":"testing 3"}); WriteResult({ "nInserted" : 1 }) MongoCapp24004:PRIMARY> db.coll_rpti_test.find({}); { "_id" : ObjectId("63f42afce069dfe79efe871c"), "name" : "目标恢复时间点" } { "_id" : ObjectId("63f42bf8e069dfe79efe871d"), "name" : "testing 1" } { "_id" : ObjectId("63f42bfae069dfe79efe871e"), "name" : "testing 2" } { "_id" : ObjectId("63f42bfde069dfe79efe871f"), "name" : "testing 3" }

d)我们把全量和oplog的备份信息(备份路径的文件夹名称为:pbmPitr )拷贝到目标的机器上,这里我们的filesystem 的路径保持一致

INFRA [mongo@wqdcsrv3059 local_backups]# scp -r ./2023-02-21T07:17:36Z mongo@10.67.200.34:/data/local_backups INFRA [mongo@wqdcsrv3059 local_backups]# scp -r ./2023-02-21T07:17:36Z.pbm.json mongo@10.67.200.34:/data/local_backups INFRA [mongo@wqdcsrv3059 local_backups]# scp -r ./pbmPitr mongo@10.67.200.34:/data/local_backups

文件拷贝过去后,我们需要 使用 backup list 查看一下 备份集是否存在:

INFRA [mongo@wqdcsrv3062 ~]# /opt/percona/percona-backup-mongodb-2.0.3/pbm list Backup snapshots: 2023-02-21T07:17:36Z <logical> [restore_to_time: 2023-02-21T07:18:02Z] PITR <off>: 2023-02-21T07:18:03Z - 2023-02-21T07:30:40Z

如果你使用 backup list 查询不到备份的信息的话, 需要执行 --force-resync 一下 强制同步一下

INFRA [mongo@wqdcsrv3062 local_backups]# /opt/percona/percona-backup-mongodb-2.0.3/pbm config --force-resync Storage resync started

e)恢复数据库到时间点 T1

INFRA [mongo@wqdcsrv3062 ~]# /opt/percona/percona-backup-mongodb-2.0.3/pbm restore --time="2023-02-21T07:20:00" Starting restore to the point in time '2023-02-21T07:20:00'...Restore to the point in time '2023-02-21T07:20:00' has started

我们可以在后台查看 pbm-agent 的日志: 基于时间点的逻辑恢复的原理就是 mongodump + oplog 回放到 指定的时间点

2023-02-21T15:38:25.000+0800 I [pitrestore/2023-02-21T07:37:27.953549651Z] restoring users and roles 2023-02-21T15:38:25.000+0800 I [pitrestore/2023-02-21T07:37:27.953549651Z] moving to state dumpDone 2023-02-21T15:38:27.000+0800 I [pitrestore/2023-02-21T07:37:27.953549651Z] starting oplog replay 2023-02-21T15:38:27.000+0800 D [pitrestore/2023-02-21T07:37:27.953549651Z] + applying {MongoCapp24004 2023-02-21T07:17:36Z/MongoCapp24004/local.oplog.rs.bson.s2 s2 {1676963858 1} {1676963882 4} 0} 2023-02-21T15:38:27.000+0800 D [pitrestore/2023-02-21T07:37:27.953549651Z] + applying {MongoCapp24004 pbmPitr/MongoCapp24004/20230221/20230221071738-1.20230221071802-4.oplog.s2 s2 {1676963858 1} {1676963882 4} 0} 2023-02-21T15:38:27.000+0800 D [pitrestore/2023-02-21T07:37:27.953549651Z] + applying {MongoCapp24004 pbmPitr/MongoCapp24004/20230221/20230221071802-4.20230221072415-3.oplog.s2 s2 {1676963882 4} {1676964255 3} 0} 2023-02-21T15:38:27.000+0800 I [pitrestore/2023-02-21T07:37:27.953549651Z] oplog replay finished on {1676963998 1} 2023-02-21T15:38:28.000+0800 I [pitrestore/2023-02-21T07:37:27.953549651Z] recovery successfully finished

f)登录恢复好的数据库实例:检查 coll_rpti_test 的 内部数据

MongoCapp24004:PRIMARY> db.coll_rpti_test.find({}); { "_id" : ObjectId("63f4709a22c55beb6fb499c0"), "name" : "目标恢复时间点" }

写到最后,目前测试发现的几点问题:
(关于percona论坛我的提问的link: https://forums.percona.com/t/some-question-about-percona-mongo-backup-tools/20208)

1.关于备份集的加密,目前看只有 remote 的存储AWS S3支持, 目前备份到filesystem 暂不支持。
参考percona 论坛: https://forums.percona.com/t/encryption-at-rest-with-percona-mongodb-backups/10835

2.物理部分暂时不支持 incremental 的方式, 如果备份策略是 full + incremental 的方式,只能用 logical 的备份方式,
Logical 的备份会连实例读取数据,无论从性能上还是时间上都是有所损耗的,建议从secondary 节点备份。
(最近版本2.0.3已经开始支持,但是官网上明确不建议在生产上使用: This is a tech preview feature. We recommend using it only for testing purposes)

https://docs.percona.com/percona-backup-mongodb/usage/incremental-backup.html

3.目前通过命令无法指定 parallel 的并行数量 ,不知道未来版本会不会支持

4.Percona backup manager 备份目标的 replica set 必须要 设置enableMajorityReadConcern :ture , 保证大多数读的一致性, 如果mongo replica set 是跨DC的多个节点,会因为网络延时造成严重的性能问题。
(如果replica set的所有节点 都在同一个DC,可以忽略此问题)

也会我们还可以等等 percona mongo backup 的未来版本 , 会不会针对以上几点进行改进 ,毕竟是免费的工具,我们不能要求的太多。

Have a fun 🙂 !

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论