mongodb备份与恢复方法大全

时间:15-01-27 栏目:云计算运维, 大数据技术文章, 数据库 作者:爱说云网 评论:0 点击: 4,026 次

数据定期备份是非常有必要的,数据的重要性不言而喻,地球上的猪都会知道。
mongodb备份方式有三种,下面分别说到:
1. 文件快照方式
2. 复制数据文件方式
3. 使用mongodump方式

一. 备份单台mongodb

1. 文件快照方式

这是最简单的备份方法。但是,需要系统文件支持快照和mongod必须启用journal。如果都符合这两条要求,可以在任何时刻创建快照。

恢复时,确保没有运行mongod,执行快照恢复操作命令,然后启动mongod进程,mongod将重放journal日志。

2. 复制数据文件方式

直接拷贝数据目录下的一切文件。但是在拷贝过程中必须阻止数据文件发生更改。因此需要对数据库加锁,以防止数据写入。

1
> db.fsyncLock()

上面的命令将阻塞写入操作,并将脏数据刷新到磁盘上,确保数据一致。
然后,拷贝数据文件到备份目录下

1
# cp -R /data/db/* /backup

文件复制完成后,对数据库进行解锁,允许写操作

1
> db.fsyncUnlock()

注意: 在执行db.fsyncLock()和db.fsyncUnlock()时,不能关闭当前的shell窗口,否则可能无法连接而需要重新启动mongod服务。

恢复时,确保mongod没有运行,清空数据目录,将备份的数据拷贝到数据目录下,然后启动mongod

1
2
# cp -R /backup/* /data/db/
# mongod -f mongod.conf

3. 使用mongodump方式

千万不要fsyncLock与mongodump配合使用,如果数据库被锁定了,mongodump将永远挂起。 
使用mongodump备份比较慢,在备份复制集时还有些问题,后续会说到。但是,用来备份单个数据库、集合、子集合还是比较好的方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# ./mongodump --help
options:
  --help                                显示帮助信息
  -v [ --verbose ]                      打印出更多信息,如时间等等 -vvvvv
  --version                             打印版本信息
  -h [ --host ] arg                     指定连接的mongodb主机,复制集时设置为<set name>/s1,s2
  --port arg                            指定mongodb端口号,也可以这么指定--host hostname:port
  --ipv6                                启用支持IPv6 support
  -u [ --username ] arg                 用户名
  -p [ --password ] arg                 密码
  --authenticationDatabase arg          user source (defaults to dbname)
  --authenticationMechanism arg (=MONGODB-CR)
                                        authentication mechanism
  --dbpath arg                          直接访问mongod的数据库文件,而不是连接到mongodb服务器。需要锁定数据目录,如果mongod当前在访问相同路径将不能使用。也就是说,mongod运行的情况下不能使用--dbpath,mongod未运行的情况下可以直接指定--dbpath
  --directoryperdb                      每个db一个单独的目录,需要指定dbpath
  --journal                             启用journaling,需要指定dbpath
  -d [ --db ] arg                       指定数据库
  -c [ --collection ] arg               指定集合
  -o [ --out ] arg (=dump)              指定输出目录,"-"表示标准输出
  -q [ --query ] arg                    json查询
  --oplog                               使用oplog来生产时间点快照
  --repair                              尝试恢复崩溃的数据库
  --forceTableScan                      强制表扫描,不使用$snapshot
1
# mongodump -p 27017

将在当前目录下创建dump目录,备份所有的数据库,所有的数据存储在.bson文件中,可以使用mongodb提供的bsondump工具来检索它。
mongod未运行情况下:

1
# mongodump --dbpath /data/db

恢复时,使用mongorestore工具恢复

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# ./mongorestore --help   //相同部分参数意义参加上面的mongodump
  -v [ --verbose ]                     
  --version                            
  -h [ --host ] arg                    
  --port arg                           
  --ipv6                               
  -u [ --username ] arg                
  -p [ --password ] arg                
  --authenticationDatabase arg         
  --authenticationMechanism arg (=MONGODB-CR)
  --dbpath arg                        
  --directoryperdb                     
  --journal
  -d [ --db ] arg 
  -c [ --collection ] arg 
  --objcheck                            在插入前验证对象,默认启用
  --noobjcheck                          不在插入前验证对象
  --filter arg                          插入前过滤
  --drop                                在插入前删除所有文档
  --oplogReplay                         在恢复时应用oplog
  --oplogLimit arg                      include oplog entries before the
                                        provided Timestamp (seconds[:ordinal])
                                        during the oplog replay; the ordinal
                                        value is optional
  --keepIndexVersion                    don't upgrade indexes to newest version
  --noOptionsRestore                    don't restore collection options
  --noIndexRestore                      don't restore indexes
  --w arg (=0)                          minimum number of replicas per write

恢复整个数据库:

1
# mongorestore -p 27017 dump/

恢复到特定的库和集合:

1
# mongorestore --db ttlsa_com --collection posts dump/old_ttlsa_com/old_posts.bson

注意: mongodump和mongorestore版本最好相匹配。

二. 备份复制集

通常情况下,在secondary进行备份,降低primary负载,只在secondary上锁定,以免影响业务(假设没有发送读请求到secondary)。 可以使用上面的任意方式进行备份,不过推荐使用文件快照方式和复制数据文件方式。 
使用mongodump备份,上面提到了一个问题,那就是在mongodump备份过程中,发生写操作。在复制集架构环境下,要避免这种情况发生,mongodump需要加上--oplog参数,来跟踪备份时服务器上发生的所有操作,获取一个pointin-time快照,否则备份的状态将与集群中其他节点不匹配。在恢复时,还必须创建oplog,并指定--oplogReplay参数来应用这些操作,否则恢复的成员将不知道从何处开始同步,从而在某个时间点上与源服务器保持一致。

在备份复制集时,可以设置mongodump连接"setName/s1,s2,s3", 它会自动选择一个可用的secondary进行备份。

备份复制集:

1
# mongodump -h "ttlsa/10.1.1.155,10.1.1.156,10.1.1.157" --oplog -o /backup/mongodbbackup/

恢复复制集步骤:

1. 将复制集中要恢复的成员移除集群

2. 运行mongorestore --oplogReplay命令

1
# mongorestore --oplogReplay dump/

3. 创建oplog

1
2
> use local
> db.createCollection("oplog.rs", {"capped" : true, "size" : 10000000})

4. 恢复oplog

1
# mongorestore -d local -c oplog.rs dump/oplog.bson

注意:oplog.bson不位于dump/local/oplog.rs.bson, oplog.bson记录mongodump过程中发生的操作。

5. 将该节点添加到复制集集群中

复制集的相关操作参见 http://www.ttlsa.com/html/1679.html

三. 备份分片

在分片集群下,不可能在一个时间点上得到一个完整集群状态的快照。当集群越来越大时,从备份恢复整个架构的几率越来越小的。 因此,对于分片集群的备份,只需独自备份config server和复制集。 
在对分片集群进行备份与恢复操作前,要关闭balancer。

对于比较小的分片集群,可以直接从mongos来备份与恢复。

在大多数情况下,我们只需要恢复集群中的某个节点。 如果需要恢复整个集群,那你够倒霉的了,整个集群数据丢失可能性比较小的。备份时,直接连接分片集群的mongod而不是通过mongos。

对于比较小型的分片集群,可以直接通过mongodump连接到mongos进行备份,备份的文件将包含config服务器的元数据信息和实际数据。

对于大型的分片集群,备份步骤如下:

1. 关闭balancer

注意:连接到mongos而不是config server实例。

1
2
3
4
> sh.setBalancerState(false) 或
> sh.stopBalancer() 或
> use config
> db.settings.update( { _id: "balancer" }, { $set : { stopped: true } } , true );

2. 备份集群元数据

使用mongodump备份任意一台config server。

可以直接连接任意一台的config mongod实例,也可以通过mongos连接。

1
# mongodump --db config

3. 备份shard集群内各个replica set

可并行执行。

4. 启用balancer

注意:连接到mongos而不是config server实例。

1
2
3
4
> sh.setBalancerState(true) 或
> sh.startBalancer() 或
> use config
> db.settings.update( { _id: "balancer" }, { $set : { stopped: false } } , true );

 

四. 适用于mongodb任何架构(standalon、replic set、sharding)备份脚本

需要安装perl的MongoDB模块,安装方法参见:使用cpanm安装perl相关模块 http://www.ttlsa.com/html/2030.html 。代码这东西,仁者见仁智者见智,一分价钱一分货,所以对于优秀的程序员不要抠门。对语言的熟练度高,编程经验丰富的程序员,写出来的代码,两个字:漂亮!

下面的脚本只需更改变量$mongodb相关参数即可,如有更好的更便捷的方法请赐教。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#!/bin/perl
#################################
### author: www.ttlsa.com     ###
### QQ群: 39514058            ###
### E-mail: service@ttlsa.com ###
#################################
use strict;
use File::Path;
use POSIX;
use MongoDB;
use Data::Dumper;
my $mongodump='/usr/local/mongodb/bin/mongodump';
my $mongodb={
    'admin_1'=>{    #定义组别
        'email'=>'39514058@qq.com',  #定义备份出错时邮件通知地址,此处未包含该功能。
        'server'=>[     #定义mongodb相关信息
            {
            'replset'=>1,    #是否复制集
            'sharding'=>0,   #是否分片
            'setname'=>"TTLSA_COM",  #复制集名称
            'mongodsvr'=>["10.1.11.155:27017","10.1.11.156:27017","10.1.11.157:27017"],   #mongod服务器IP和端口号
            'configsvr'=>[],  #config server服务器IP和端口号
            'mongossvr'=>[],  #mongos server服务器IP和端口号
            'backupdir'=>"/data/backup/mongodb_ttlsa_com",  #备份目录
            'user'=>"",      #用户名
            'passwd'=>"",    #密码
            'interval'=>15,  #备份轮滚周期
            },
            {
            'replset'=>1,
            'sharding'=>1,
            'setname'=>"shard1",
            'mongodsvr'=>["10.1.22.21:27029","10.1.22.22:27029","10.1.22.23:27029"],
            'configsvr'=>["10.1.22.21:27028","10.1.22.22:27028","10.1.22.23:27028"],
            'mongossvr'=>["10.1.22.21:27027","10.1.22.22:27027","10.1.22.23:27027"],
            'backupdir'=>"/data/backup/mongodb_shard1",
            'user'=>"",
            'passwd'=>"",
            'interval'=>15,
            },
            {
            'replset'=>0,
            'sharding'=>0,
            'setname'=>"shard1",
            'mongodsvr'=>["10.1.27.22:30000","10.1.27.22:30001","10.1.20.16"],
            'configsvr'=>[],
            'mongossvr'=>[],
            'backupdir'=>"/data/backup/mongodb_standalon",
            'user'=>"root",
            'passwd'=>"www.ttlsa.com",
            'interval'=>15,
            }
            ]},
        #'admin_2'=>{}          
};
while(my($group,$value)=each(%$mongodb)){
    foreach my $node (@{$value->{'server'}}){
        my $tmp_stdout = tmpnam();
        my $tmp_stderr = tmpnam();
        if($node->{'replset'} && !$node->{'sharding'}){
            my $dir = $node->{'backupdir'};
            mkpath $dir unless -e $dir;
            my $return=backup_rotate($dir,$node->{'interval'});
            my $hosts = $node->{'setname'}.'/'.join(',', @{$node->{'mongodsvr'}});
            if(($node->{'user'} ne '') && ($node->{'passwd'} ne '')){
                my $retval=system("$mongodump -vvvvv -h $hosts -u $node->{'user'} -p $node->{'passwd'} --oplog -o $dir/dump.1 >$tmp_stdout 2>$tmp_stderr");
            }else{
                my $retval=system("$mongodump -vvvvv -h $hosts --oplog -o $dir/dump.1 >$tmp_stdout 2>$tmp_stderr");
            }
        }elsif($node->{'sharding'}){
            my $mongod_hosts=$node->{'setname'}.'/'.join(',', @{$node->{'mongodsvr'}});
            my $mongos_hosts=$node->{'setname'}.'/'.join(',', @{$node->{'mongossvr'}});
            my $mongod_dir = $node->{'backupdir'}.'/'.'mongodsvr';
            my $config_dir = $node->{'backupdir'}.'/'.'configsvr';
            mkpath $mongod_dir unless -e $mongod_dir;
            mkpath $config_dir unless -e $config_dir;
            my $return=backup_rotate($mongod_dir,$node->{'interval'});
            my $return=backup_rotate($config_dir,$node->{'interval'});
            if(($node->{'user'} ne '') && ($node->{'passwd'} ne '')){
                my $conn = MongoDB::Connection->new("host" => "mongodb://$mongos_hosts","db_name" => "admin", "username" => "$node->{'user'}", "password" => "$node->{'passwd'}");
                my $db = $conn->get_database('config');
                my $coll=$db->get_collection('settings');
                my $ret=$coll->update({ _id => "balancer" }, { '$set' => { 'stopped'=> 'true' } },{'false'},{'true'});
                my $retval=system("$mongodump -h $mongos_hosts -u $node->{'user'} -p $node->{'passwd'} --db config -o $config_dir/dump.1 >$tmp_stdout 2>$tmp_stderr");
                my $retval=system("$mongodump -h $mongod_hosts -u $node->{'user'} -p $node->{'passwd'} --oplog -o $mongod_dir/dump.1 >$tmp_stdout 2>$tmp_stderr");
                my $ret=$coll->update({ _id => "balancer" }, { '$set' => { 'stopped'=> 'false' } },{'false'},{'true'});
            }else{
                my $conn = MongoDB::Connection->new("host" => "mongodb://$mongos_hosts");
                my $db = $conn->get_database('config');
                my $coll=$db->get_collection('settings');
                my $ret=$coll->update({ _id => "balancer" }, { '$set' => { 'stopped'=> 'true' } },{'false'},{'true'});
                my $retval=system("$mongodump -h $mongos_hosts --db config -o $config_dir/dump.1 >$tmp_stdout 2>$tmp_stderr");
                my $retval=system("$mongodump -h $mongod_hosts --oplog -o $mongod_dir/dump.1 >$tmp_stdout 2>$tmp_stderr");
                my $ret=$coll->update({ _id => "balancer" }, { '$set' => { 'stopped'=> 'false' } },{'false'},{'true'});
            }
        }else{
            foreach my $each (@{$node->{'mongodsvr'}}){
                my $dir = $node->{'backupdir'}.'/'.$each;
                mkpath $dir unless -e $dir;
                my $return=backup_rotate($dir,$node->{'interval'});
                if(($node->{'user'} ne '') && ($node->{'passwd'} ne '')){
                    my $retval=system("$mongodump -h $each -u $node->{'user'} -p $node->{'passwd'} -o $dir/dump.1 >$tmp_stdout 2>$tmp_stderr");
                }else{
                    my $retval=system("$mongodump -h $each -o $dir/dump.1 >$tmp_stdout 2>$tmp_stderr");
                }
            }
        }
    }
}
sub backup_rotate {
    my $backup_dir=shift;
    my $retral=shift;
    my @aa=sort{$b<=>$a} 1..$retral;
    if(chdir "/$backup_dir"){
        for my $num (@aa){
            my $old=$num+1;
            if(-e "dump.$num"){
                if(-e "dump.$old"){
                    system("rm -rf dump.$old && mv dump.$num dump.$old");
                }else{
                    system("mv dump.$num dump.$old");
                }
            }
        }
    }else{
       return "Failed to change dir $backup_dir : $!";
    }
}

五. MongoDB增量备份方法

上一篇《mongodb备份与恢复(上)》http://www.ttlsa.com/html/1938.html 说到的方法都需要拷贝所有数据,即使数据发生很少的改变。如果数据量很大的话,备份整个数据库将消耗更多的时间和磁盘空间。这时增量备份将会是个必然的选择,记录前一次的完整备份点,后续的备份只备份从该点发生改变的数据。 
这种方法需要一台专门的备份服务器backup_server,当然backup_server需要一个完整的备份,然后通过mongooplog工具来拷贝并应用mongodb_server的oplog日志。 
在mongodb_server上执行以下操作:

1
2
> op = db.oplog.rs.find().sort({$natural: -1}).limit(1).next();
> start = op['ts']['t']/1000

在backup_server上执行:

1
# mongooplog --from A --seconds SECOND

SECOND值位于start值与当前时间之间。

mongooplog工具介绍:
mongooplog从远程拉取oplog日志并应用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# ./mongooplog --help
  --help                          显示帮助信息
  -v [ --verbose ]                打印出更多信息,如时间等等 -vvvvv
  --version                       打印版本信息
  -h [ --host ] arg               指定连接的mongodb主机,复制集时设置为<set name>/s1,s2
  --port arg                      指定mongodb端口号,也可以这么指定--host hostname:port
  --ipv6                          启用支持IPv6
  -u [ --username ] arg           用户名
  -p [ --password ] arg           密码
  --dbpath arg                    直接访问mongod的数据库文件,而不是连接到mongodb服务器。需要锁定数据目录,如果mongod当前在访问相同路径将不能使用。也就是说,mongod运行的情况下不能使用--dbpath,mongod未运行的情况下可以直接指定--dbpath
  --directoryperdb                每个db一个单独的目录,需要指定dbpath
  --journal                       启用journaling
  -d [ --db ] arg                 指定数据库
  -c [ --collection ] arg         指定集合(some commands)
  -f [ --fields ] arg             逗号分隔的列名,如-f name,age
  --fieldFile arg                 file with fields names - 1 per line
  -s [ --seconds ] arg            seconds to go back default:86400
  --from arg                      host to pull from
  --oplogns arg (=local.oplog.rs) ns to pull from

六. 10gen发布MongoDB增量备份服务

提供支持按照指定时间点恢复的持续增量备份功能, 不过需要支付的。 
提供的特性有:mongodb备份与恢复(下) 
1. 用于数据传输的SSL加密 
2. 高可用性 
3. 指定时间点恢复 
4. 支持分片集群 
5. 较低的开销

工作原理:
是一个轻量级代理,它从所有正在备份的副本集合中收集oplog,将其压缩并加密,然后通过SSL发送到运行备份服务的数据中心。
此方法的好处有:
1. 数据是增量备份的,因此传输的数据相对较小
2. 备份服务中的数据与主系统中的数据在时间上非常接近
3. 对主系统的影响不会比向副本集合中添加另一个副本大(后者非常缓慢, 可先恢复到最新备份状态,然后在加入集群中同步)
4. oplog支持将副本集合恢复到任意时间点。

有两个备份选项:快照和自定义快照。
备份服务依据一套策略创建和维持备份快照。这些快照中的任何一个都可以用于恢复。同样的,用户也可以指定一个自己希望使用的精确时间点创建一份快照。在这种情况下,将使用该时间点之前最新的快照,并会根据用户指定的时间点应用oplog。

相关文章

谷歌技术”三宝”之谷歌文件系统(GFS) — 大数据云计算时代...
views 2489
虽然"The Google File System " 是 03年发表的老文章了,但现在仍被广泛讨论,其对后来的分布式文件系统设计具有指导意义。然而,作者在设计GFS时,是基于过去很多实验观察的,并提出了 很多假设作为前提,这等于给出了一个GFS的应用场景。所以我们自己在设计分布式系统时,一定要注意...
大数据未来发展趋势预测
views 2662
大数据的世界正在稳步发展壮大。随着数据数量和种类的不断膨胀,读者都想知道接下来会发生什么。Sriram Mohan博士是罗斯豪曼理工学院计算机科学和软件工程的副教授。同时他还兼任着Avalon咨询公司大数据解决方案高级顾问一职。他融汇理论与实践于一身,他绝对是回答“2014年企业大数据发展趋势”的正...
大数据时代,课堂应如何创新
views 1782
随着大数据时代出现,有人曾这样预言,随着MOOC、微课、翻转课堂等基于网络的教学形式的出现,我们这些中小学教师弄不好是会下岗的。 这也许不是危言耸听。 当我们孩子天天拿着IPAD,随时随地搜索、了解各种知识、资讯时,他们是这个互联网时代的原住民,而我们从“50后”到“80后”的教师,充其量只是网络世...
apache hadoop简介及核心机制
views 1854
Hadoop是什么?Hadoop是一个开发和运行处理大规模数据的软件平台,是Appach的一个用java语言实现开源软件框架,实现在大量计算机组成的集群中对海量数据进行分布式计算. Hadoop框架中最核心设计就是:HDFS和MapReduce.HDFS提供了海量数据的存储,MapReduce提供了...
大数据被媒体和一帮理工文盲玩坏了
views 1348
 现在大数据被媒体一帮理工文盲玩坏了。。。觉得数据量大就是大数据,或者甚至里面数字大也是大数据。。。。唉 请问统计个搜索量跟大数据有什么关系......   所谓Big Data其实是有两部分组成的。一部分是海量运算存储能力,一部分是数据建模算法。   第二部分其实是一个蛮久的学科了。20年...
云计算“三国时代”:百度有开发者,阿里靠中间人,腾讯要突围...
views 1748
云计算“三国时代”:百度有开发者,阿里靠中间人,腾讯要突围   自从2013年9月腾讯云推出之后,中国云计算市场正式进入三国时代。尽管微软、亚马逊云服务均已入华,中国三大运营商也有云计算产品,京东、新浪等“小巨头”也有云计算产品,但相比三大互联网巨头而言,它们并没有多少存在感。云计算不...
了解用于大数据解决方案的逻辑层-技术方案...
views 1381
文中介绍的模式有助于定义大数据解决方案的参数。本文将介绍最常见的和经常发生的大数据问题以及它们的解决方案。原子模式描述了使用、处理、访问和存储大数据的典型方法。复合模式由原子模式组成,并根据大数据解决方案的范围进行分类。由于每个复合模式都有若干个维度,所以每个模式都有许多变化。复合模式使得业务和技术...
如何应对云计算大数据带来的法律问题...
views 1896
云计算给人们带来的一个最直观的感觉就是,大量的数据集中在“云”里,抬头观天,“我”在哪里?   物联网给人们最直观的感觉是,任何一个结点的传感器都在收集数据,低头看路,“陷阱”在哪里。   当一个人如此多的信息被陌生的机构掌握时,产生恐惧和不安全感一定是很正常的事情,于是自然会想到一个问题,如何...

声明: 本文由( 爱说云网 )原创编译,转载请保留链接: mongodb备份与恢复方法大全

mongodb备份与恢复方法大全:等您坐沙发呢!

发表评论


读者排行