mongodb备份与恢复方法大全

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

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

相关文章

大数据平台核心竞争力:业务敏捷性,实时性,性能 – hadoop技术学习 (欢迎关注同名...
views 1769
最近在考虑新一年的架构的时候,我就在想一个大数据平台核心竞争力到底是什么?每个平台发展的阶段可能不太一样,所以所需要的核心竞争力不同。但是做架构,做设计的朋友一定要常常思考下你负责的平台到底核心竞争力是什么。 我们现在做的平台不是自用的,是销售给第三方。我觉得排在前三核心竞争力分别是:   1、业务...
大数据与网络黑产
views 2570
随着互联网不断深度介入人们的生活,网络上也在源源不断积累起大量数据。这些数据就像散落在互联网生态中的粒粒珍珠,诱惑着网络黑产分子瞪大贪婪的双眼,伺机而动…… 记者调查发现,基于这些存在的产业链,上游,是以技术含量最高的职业黑客为主,他们通过挖掘漏洞、编写木马实施入侵,获取数据;中游,是购买这些数据...
芝麻开门 大数据征信体系揭秘
views 2584
1月28日,蚂蚁金融服务集团(下称“蚂蚁金服”)旗下的芝麻信用首次测试个人征信系统,这也是1月5日央行发布允许8家机构进行个人征信业务准备工作通知后,首家推出该系统的公司。据21世纪经济报道记者了解,在1月5日央行发布通知后,蚂蚁金服便迅速注册公司,组建团队。其骨干成员大部分为数据科学 家,同时开始...
42页PPT干货!R在行动广告大数据的应用-技术方案...
views 1146
网易的实时计算需求 对于大多数的大数据而言,实时性是其所应具备的重要属性,信息的到达和获取应满足实时性的要求,而信息的价值需在其到达那刻展现才能利益最大化,例如电商网站,网站推荐系统期望能实时根据顾客的点击行为分析其购买意愿,做到精准营销。 实时计算指针对只读(Read On...
大数据时代,科技走到了宗教尽头
views 1650
这是一个人人都言“大数据”的时代,然“大数据”存在于何处?影响于何处?难免,普通大众被席卷而来的“大数据”之潮迷乱了眼睛,搅乱了思绪。正是在这样的时刻,笔者认为尤为重要的是保有敬畏之心与清醒的思维,认识到“大数据”的局限性。 渗透时刻,无处不在的大数据 大数据可能是时下最吸引眼球的话题之一。从通过...
数据可视化、信息可视化、知识可视化-技术方案...
views 1963
 概述   数据可视化主要旨在借助于图形化手段,清晰有效地传达与沟通信息。但是,这并不就意味着,数据可视化就一定因为要实现其功能用途而令人感到枯燥乏味,或者是为了看上去绚丽多彩而显得极端复杂。为了有效地传达思想概念,美学形式与功能需要齐头并进,通过直观地传达关键的方面与特征,从而实现对于相当稀疏而又...
看大数据如何改变音乐产业
views 1155
行业领导者继续将音乐的版权使用费视为重中之重,认为它才是艺术家们收入的唯一未来。然而,音乐商业化的命运依然前途未卜。有些人认为我们的目标仅是简单地将艺术家的音乐传送到消费者的耳朵里。其他人则认为应该继续由消费者为音乐服务买单。不过,对那些音乐创作者来说,不管他们是签约音乐人还是独立音乐人,订阅模式...
专访携程大数据平台高级经理李亚锋:大数据技术融合下的Spark更具魅力...
views 1312
随着移动互联时代的到来,人们的双手得到解放,因为通过智能手机APP和触摸屏就可以彻底解决交互性和易用性的问题,这也使用户行为数据呈现爆炸性增长。大数据技术可以帮助我们对海量的数据进行加工分析,了解用户的行为特征,以及他们对服务的期待,从而使用户得到更好的服务体验。 Hadoop 和Spark都是大家...

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

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

发表评论


读者排行