mongodb备份与恢复方法大全

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

数据定期备份是非常有必要的,数据的重要性不言而喻,地球上的猪都会知道。
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。

相关文章

2014中关村大数据日,数据资产驱动产业创新...
views 1702
大数据作为价值万亿的可再生之矿,作为社会资产和生产要素,影响国计民生、产业再造和民族复兴。如何对数据资产的管理、变现和驱动产业创新,决定企业的竞争能力,产业的未来和国家竞争力。 围绕这个话题,政府领导、行业领袖、技术专家怎么看?产业联盟,领军企业和产业代表怎么想,又怎么做?2014中关村大数据日,我...
云计算背景下的大数据时代来临
views 1852
数据中心正在成为新时代的“信息电厂”,成为知识经济的基础设施。过去一年,“大数据”正在成为一个热门话题。 半个世纪信息技术的发展,主要解决的是云计算中“结构性”数据的存储、处理与应用。“结构性”数据的特征有如你到银行去存取款,银行的计算机系统记录着你的名字,在名字之后是你存取款的数量、时间、类型等信...
NoSQL代表: Mongo DB(芒果数据库)
views 2142
 一、MongoDB简介         MongoDB是一个基于分布式文件存储的数据库,由C++语言编写,旨在为WEB应用提供可扩展的高性能数据存储解决方案。其名字来自humongous这个单词的中间部分,从名字可见其野心所在就是海量数据的处理。(humongous:堆积如山)2011年将被记住,...
42页PPT干货!R在行动广告大数据的应用-技术方案...
views 1505
网易的实时计算需求 对于大多数的大数据而言,实时性是其所应具备的重要属性,信息的到达和获取应满足实时性的要求,而信息的价值需在其到达那刻展现才能利益最大化,例如电商网站,网站推荐系统期望能实时根据顾客的点击行为分析其购买意愿,做到精准营销。 实时计算指针对只读(Read On...
大数据时代引发安全问题,应增强身份管理...
views 1740
2014年,虽然大数据应用还没有深入普及,但是已经有越来越多的行业用户尝试引入大数据相关技术解决如何管理、利用日益增长的各类数据,而往往随之的安全问题也日益受到关注,为了确保防止黑客盗 窃数据信息的风险,企业应该在转移到充分利用大数据的优势的同时,也相当有必要采取相关的安全措施来保护他们数据资产的完...
大数据未来发展趋势预测
views 2974
大数据的世界正在稳步发展壮大。随着数据数量和种类的不断膨胀,读者都想知道接下来会发生什么。Sriram Mohan博士是罗斯豪曼理工学院计算机科学和软件工程的副教授。同时他还兼任着Avalon咨询公司大数据解决方案高级顾问一职。他融汇理论与实践于一身,他绝对是回答“2014年企业大数据发展趋势”的正...
百度大数据洞察:“数”说年轻女性的自我世界-应用案例...
views 1834
  百度大数据带您透视小世界里的大女人精神。小世界指的是新一代年轻女性的自我世界,寓意每一个小小的我都是一个世界;大女人寓意新一代年轻女性脱离集体意识形态,不再完全秉承传统女性小鸟依人式的附属与顺从,而体现为一种独立自主的精神、一种大女人的情怀。   新一代年轻女性自我意识崛起下的3个需求层次  ...
浅析大数据与云计算物联网等热点的关系...
views 1917
  大数据时代的到来,是全球知名咨询公司麦肯锡最早提出的,麦肯锡称:“数据,已经渗透到当今每一个行业和业务职能领域,成为重要的生产因素。人们对于海量数据的挖掘和运用,预示着新一波生产率增长和消费者盈余浪潮的到来。” 近几年大数据一词的持续升温也带来了大数据泡沫的疑虑,大数据的前景与目前云计算、物联网...

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

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

发表评论


读者排行