Dragon
主机之家测评主机之家测评  2019-08-27 22:12 主机之家测评 隐藏边栏 |   抢沙发  92 
文章评分 0 次,平均分 0.0

最近数据库真是多灾多难,前段时间刚刚爆出 MongoDB 数据库安全问题。这两天又被炉石传说数据库故障给刷屏了。

从炉石传说数据库故障谈谈 MongoDB 的数据库备份和恢复手段

看到这个消息,我的第一反应是重新翻出尘封已久的 ipad,装上炉石准备上线领补偿。等等,作为一个数据库行业从业人员,是不是还应该干点什么?恩,很有必要再重新审视一下我们的数据库有没有做好容灾,否则,今天你看别人热闹,明天可能就别人看你热闹了。借此机会我想给大家普及一下 MongoDB 数据库的备份和恢复手段(当然炉石传说应该不一定是使用 MongoDB 作为数据库),以帮助大家做好容灾,过个好年。同时,我也为我们阿里云 MongoDB 服务做下广告,我们的 MongoDB 服务拥有完善的自动备份/恢复功能,灵活的备份策略,好用的恢复到任意时间点功能。我们的备份存放了多份副本,可靠性达 10 个 9,请大家放心使用!

MongoDB 数据库备份手段

全量逻辑备份/恢复

Mongodump/Mongorestore

对于数据量比较小的场景,使用官方的mongodump/mongorestore工具进行全量的备份和恢复就足够了。mongodump 可以连上一个正在服务的 mongod 节点进行逻辑热备份。其主要原理是遍历所有集合,然后将文档一条条读出来,支持并发 dump 多个集合,并且支持归档和压缩,可以输出到一个文件(或标准输出)。同样,mongorestore 则是连上一个正在服务的 mongod 节点进行逻辑恢复。其主要原理是将备份出来的数据再一条条写回到数据库中。

对性能的影响

mongodump 执行过程由于会遍历所有数据,因此会对 MongoDB 性能有影响,最好在备节点执行(最好是 hidden,需检查备节点数据同步是否正常)。

获取一致的数据快照

在 mongodump 执行过程中由于数据库还有新的修改,直接运行 dump 出来的结果不是一个一致的快照,需要使用一个『--oplog』的选项来将这个过程中的 oplog 也一块 dump 下来(使用 mongorestore 进行恢复时对应要使用--oplogReplay 选项对 oplog 进行重放)。而由于 MongoDB 的 oplog 是一个固定大小的特殊集合,当 oplog 集合达到配置的大小时旧的 oplog 会被滚掉以为新的 oplog 腾出空间。在使用『--oplog』选项进行 dump 时,mongodump 会在 dump 集合数据前获取当时最新的 oplog 时间点,并在集合数据 dump 完毕之后再次检查这个时间点的 oplog 是否还在,如果 dump 过程很长,oplog 空间又不够,oplog 被滚掉就会 dump 失败。因此在 dump 前最好检查一下 oplog 的配置大小以及目前 oplog 的增长情况(可结合业务写入量及 oplog 平均大小进行粗略估计),确保 dump 不会失败。目前我们阿里云 MongoDB 服务针对 oplog 做了弹性扩缩容的优化,能够确保在逻辑备份过程中 oplog 不被滚掉,一定能够备份成功。

索引的备份和恢复

对于集合数据,mongodump 出来的结果是一个个 bson 文件。而对于集合的索引,则是描述在一个 metadata 的 json 文件里,里面还包含创建集合时所使用的选项。在使用 mongorestore 进行恢复时,会在集合数据恢复完毕之后进行对应的索引创建。

全量物理备份/恢复

对于数据量很大的场景,如果使用 mongodump/mongorestore 进行备份和恢复,需要的时间可能会很长。对于备份来说,最主要的问题就是备份所需时间越长,oplog 被滚掉的几率就越大,备份失败的几率也就越大。而对于恢复来说,由于恢复过程还涉及到索引的创建,如果除了数据量大,还有很多索引,所需花费的时间就更长了。遇到像炉石这种数据灾难,恢复时间当然是越短越好,毕竟在游戏行业分分钟的流水都很可观。这时候就需要物理备份出场了,物理备份,顾名思义就是通过物理拷贝数据文件实现备份。在恢复时可以直接使用物理备份拷贝出来的数据文件,直接启动 mongod。物理备份最大的好处是速度快,恢复时也不需要再建索引。

实施方法

物理备份通过拷贝数据文件来实现,这要求所有被拷贝的数据文件必须是一个一致的数据快照。因此物理备份的实施方法和 MongoDB 采用的存储引擎有关,并且,根据是否配置 MongoDB 打开了 Journal,在实施的细节上会有一些不同,具体可参考官方文档。不管使用何种存储引擎,在 3.2 版本之后,都可以用以下方法实现物理备份:

  1. 通过 mongoshell 执行以下命令以确保所有的写操作都 flush 到磁盘并禁止新的写入:

      
  2. 利用底层文件系统层或逻辑卷的快照功能对 MongoDB 的数据目录做快照,或直接通过 cp、scp、tar 等命令拷贝数据目录。

  3. 还是在刚才的 mongoshell 上(这里需要保证和刚刚是同一个连接),执行以下命令以重新允许新的写入:

      

由于执行 db.fsyncLock()会加数据库的全局写锁,这时数据库会处于一个不可访问的状态,因此物理备份最好也在备节点上执行(最好是 hidden,注意同样需要确保物理备份完成之后节点的 oplog 能追上主节点)。目前我们阿里云 MongoDB 团队已经研发出了无需停写服务的物理热备份手段,相信很快就可以让大家用上,尽请期待!

增量备份

MongoDB 的增量备份可以通过持续抓取 oplog 来实现,这个目前没有现成的工具可以利用,需要自己代码实现。抓取 oplog 主要的难题也和使用 mongodump 进行全量备份一样,需确保要抓取的 oplog 不被滚掉。目前我们阿里云 MongoDB 服务实现了自动增量备份的功能,结合全量备份可以实现任意时间点恢复功能。

Sharding 的备份/恢复

炉石是不分服的,因此它后面也有可能是使用分布式数据库。对于分布式数据库来说,备份和恢复比单机数据库更加复杂。分布式数据库包含多个节点,并且通常包含不同角色的节点。以 MongoDB 的 Sharding 集群为例,它包含一个保存元数据的 config server 以及若干个保存数据的 shard。其中最主要的元数据就是数据在 shard 之间的分布情况。对于多个节点的备份,其中一个难题是保证所有节点备份的数据是同一个时间点的,常规采用的手段是停止外部写入后进行备份,这在互联网服务中显然不可接受。退而求其次,可以在停止接受同步的备节点上进行备份,这样可以得到一个时间大致接近的备份。另外一个难题是各数据节点之间通常存在数据迁移,而数据迁移就涉及到起码 2 个以上数据节点的数据修改以及元数据节点的数据修改,如果在备份过程中发生数据迁移,很难保证备份出来的数据和元数据是一个一致的状态。因此通常在备份过程中需要关闭数据迁移。MongoDB 官方的文档指导步骤就是采用这个思路,先关闭负责数据迁移的 balancer,然后依次在 config server 和各个 shard 的备节点上进行备份。关闭数据迁移最大的问题是关闭期间集群无法实现数据均衡,除了会影响集群的访问性能外,还造成资源的浪费,这在数据量较大,所需备份时间较长时可能造成比较大的影响。

针对这两大难题,我们阿里云 MongoDB 团队研发了不需要停外部写,并且无需关数据迁移的 Sharding 备份手段,能够实现『任意』时间点恢复,这个功能将伴随着即将推出的 Sharding 形态一起推出,尽情期待!

阿里云 MongoDB 备份服务

阿里云 MongoDB 服务提供自动备份/恢复功能,默认每天为数据进行全量备份,并且自动抓取 oplog 进行增量备份。用户可以在控制台自定义备份策略以及进行恢复。

从炉石传说数据库故障谈谈 MongoDB 的数据库备份和恢复手段
从炉石传说数据库故障谈谈 MongoDB 的数据库备份和恢复手段

恢复时可以选择某一个备份集或某一个时间点克隆出一个新的实例,可以在新实例上进行数据校验,等校验没问题后切换到新实例。此外,全量备份的数据还提供下载功能,用户也可以选择下载备份集到本地后恢复到一个临时实例进行数据校验。

总结

说了这么多,大家应该对 MongoDB 的备份/恢复手段有了一个大概的认识。如果要图省心,还是建议直接使用阿里云 MongoDB 服务,我们有自动化的备份/恢复服务,灵活的备份策略,只需点点鼠标就能用上任意时间点恢复、物理热备份、Sharding 备份/恢复这些黑科技,从此不再为数据库容灾发愁,业务你们做,锅有我们来背,还等什么呢,快来试用吧!

本文为原创文章,版权归所有,欢迎分享本文,转载请保留出处!

发表评论

扫一扫二维码分享