ICode9

精准搜索请尝试: 精确搜索
首页 > 数据库> 文章详细

MongoDB OpLog

2022-05-20 00:02:57  阅读:210  来源: 互联网

标签:10 mongod -- MongoDB 0800 oplog 2020 OpLog


mongodump和mongorestore高级企业应用(--oplog)

注意:这是replica set或者master/slave模式专用
--oplog
 use oplog for taking a point-in-time snapshot

# 可以备份基于时间点的快照
# 在做备份过程中,把新产生的数据,以oplog快照的形式进行保存
 

oplog介绍

在replica set中oplog是一个定容集合(capped collection),它的默认大小是磁盘空间的5%(可以通过--oplogSizeMB参数修改).

位于local库的db.oplog.rs,有兴趣可以看看里面到底有些什么内容。
其中记录的是整个mongod实例一段时间内数据库的所有变更(插入/更新/删除)操作。
当空间用完时新记录自动覆盖最老的记录。
其覆盖范围被称作oplog时间窗口。需要注意的是,因为oplog是一个定容集合,
所以时间窗口能覆盖的范围会因为你单位时间内的更新次数不同而变化。
想要查看当前的oplog时间窗口预计值,可以使用以下命令:

说明:
1、oplog相当于MySQL中的binlog,保存的是MongoDB修改操作类的日志
2、他是一个定容集合,也就是固定大小不变的表
3、默认可用大小是磁盘空间的5%,可以通过oplogsizeMB参数指定
4、单节点MongoDB没有oplog,只存在于复制集中
5、可以通过以下命令监控是否够用
my_repl:PRIMARY> rs.printReplicationInfo()


oplog 什么时候可以被覆盖?
至少要预留MongoDB一个全备的周期大小
或者计划任务,每几个小时备份一次oplog

启动一下复制集:
mongod -f /mongodb/28017/conf/mongod.conf 
mongod -f /mongodb/28018/conf/mongod.conf 
mongod -f /mongodb/28019/conf/mongod.conf 
mongod -f /mongodb/28020/conf/mongod.conf 

my_repl:PRIMARY> rs.printReplicationInfo()
configured oplog size:   2048MB	 <---集合大小
log length start to end: 80641secs (22.4hrs) <---预计窗口覆盖时间
oplog first event time:  Sat Oct 24 2020 12:54:27 GMT+0800 (CST)
oplog last event time:   Sun Oct 25 2020 11:18:28 GMT+0800 (CST)
now:                     Sun Oct 25 2020 11:18:37 GMT+0800 (CST)
my_repl:PRIMARY>


# oplog在哪?
my_repl:PRIMARY> use local
switched to db local
my_repl:PRIMARY> show tables;
me
oplog.rs	#表名
replset.election
replset.minvalid
replset.oplogTruncateAfterPoint
startup_log
system.replset
system.rollback.id
my_repl:PRIMARY> 
my_repl:PRIMARY>  
my_repl:PRIMARY>  db.oplog.rs.find().pretty()
{
	"ts" : Timestamp(1603596973, 15),
	"t" : NumberLong(2),
	"h" : NumberLong("5601072907399108802"),
	"v" : 2,
	"op" : "i",
	"ns" : "simon.foo",
	"ui" : UUID("82000b1b-359c-4cc2-84a7-3be775b518a1"),
	"wall" : ISODate("2020-10-25T03:36:13.813Z"),
	"o" : {
		"_id" : ObjectId("5f94f2ad1e125066f9568858"),
		"a" : 13
	}
}
"ts" : Timestamp(1553597844, 1), //(时间戳 + 操作序列号) --->相当于GTID 
"op" : "n" //操作类型
"ns" : 		//操作对象
"o"  :

# 操作类型
"i": insert
"u": update
"d": delete
"c": db cmd
"n": NOTE 提示类操作,可以不用关注

# 查看 Create 类操作
my_repl:PRIMARY> db.oplog.rs.find( { "op" : "c"} ).pretty()
# 查看 insert 类操作
my_repl:PRIMARY> db.oplog.rs.find({"op":"i"}).pretty()


test:PRIMARY> rs.printReplicationInfo()
configured oplog size:   1561.5615234375MB <--集合大小
log length start to end: 423849secs (117.74hrs) <--预计窗口覆盖时间
oplog first event time:  Wed Sep 09 2015 17:39:50 GMT+0800 (CST)
oplog last event time:   Mon Sep 14 2015 15:23:59 GMT+0800 (CST)
now:                     Mon Sep 14 2015 16:37:30 GMT+0800 (CST)

oplog企业级应用

(1)实现热备,在备份时使用--oplog选项
注:为了演示效果我们在备份过程,模拟数据插入
(2)准备测试数据
[mongod@db01 conf]$ mongo --port 28018
use oldboy
for(var i = 1 ;i < 100; i++) {
    db.foo.insert({a:i});
}

my_repl:PRIMARY> db.oplog.rs.find({"op":"i"}).pretty()

oplog 配合mongodump实现热备
mkdir -p /mongodb/backup/opdata
mongodump --port 28017 --gzip --oplog -o /mongodb/backup/opdata

[mongod@mysql-node01 ~]$ mongodump --port 28017 --gzip --oplog -o /mongodb/backup/opdata/
2020-10-25T11:42:11.254+0800	writing admin.system.version to 
2020-10-25T11:42:11.254+0800	done dumping admin.system.version (1 document)
2020-10-25T11:42:11.255+0800	writing simon.foo to 
2020-10-25T11:42:11.255+0800	done dumping simon.foo (99 documents)
2020-10-25T11:42:11.256+0800	writing captured oplog to 
2020-10-25T11:42:11.256+0800		dumped 1 oplog entry
[mongod@mysql-node01 ~]$
[mongod@mysql-node01 ~]$
[mongod@mysql-node01 ~]$ cd /mongodb/backup/opdata
[mongod@mysql-node01 opdata]$ pwd
/mongodb/backup/opdata
[mongod@mysql-node01 opdata]$ ll
total 4
drwxrwxr-x 2 mongod mongod  75 Oct 25 11:46 admin
-rw-rw-r-- 1 mongod mongod 118 Oct 25 11:46 oplog.bson
drwxrwxr-x 2 mongod mongod  53 Oct 25 11:46 simon
[mongod@mysql-node01 opdata]$

作用介绍:--oplog 会记录备份过程中的数据变化,以快照的形式保存在oplog.bson里

恢复
mongorestore  --port 28017 --oplogReplay /mongodb/backup/opdata



--oplogReplay	# 恢复完数据文件后再重放oplog。默认回放文件是当前目录下 dump/oplog.bson
# <dump-directory>/local/oplog.rs.bson

如果oplog不在这,则可以通过下面参数指定
--oplogFile		# 指定需要重放的oplog文件位置
--oplogLimit	# 重放oplog 时截止到指定时间点

# 为了模拟dump过程中的数据变化,我们开启一个循环插入数据的线程:
# 一个窗口模拟数据插入
for (var i=0; i<100000; i++){
	db.random.insertOne({x:Math.random()*100000});
	}


# 另一个窗口 对MongoDB做 mongodump
mongodump -h localhost:27017 --oplog

oplog高级应用

背景:每天0点全备,oplog恢复窗口为48小时
某天,上午10点world.city 业务表被误删除。
恢复思路:
    0、停应用
    2、找测试库 
    3、恢复昨天晚上全备
    4、截取全备之后到world.city误删除时间点的oplog,并恢复到测试库
    5、将误删除表导出,恢复到生产库

恢复步骤:
模拟故障环境:

1、全备数据库
模拟原始数据

mongo --port 28017
my_repl:PRIMARY> use simon_db
switched to db simon_db

my_repl:PRIMARY> for(var i = 1 ;i < 20; i++) {
...     db.t1.insert({a: i});
... }
WriteResult({ "nInserted" : 1 })
my_repl:PRIMARY>

全备:
rm -rf /mongodb/backup/*
mongodump --port 28017 --oplog -o /mongodb/backup/opdata


--oplog功能:在备份同时,将备份过程中产生的日志进行备份
文件必须存放在/mongodb/backup下,自动命令为oplog.bson

[mongod@mysql-node01 backup]$ mongodump --port 28017 --oplog -o /mongodb/backup/opdata
2020-10-25T12:24:21.806+0800	writing admin.system.version to 
2020-10-25T12:24:21.807+0800	done dumping admin.system.version (1 document)
2020-10-25T12:24:21.807+0800	writing simon.foo to 
2020-10-25T12:24:21.808+0800	writing simon_db.t1 to 
2020-10-25T12:24:21.808+0800	writing test.t1 to 
2020-10-25T12:24:21.808+0800	writing test.t3 to 
2020-10-25T12:24:21.809+0800	done dumping simon_db.t1 (19 documents)
2020-10-25T12:24:21.809+0800	writing test.t2 to 
2020-10-25T12:24:21.809+0800	done dumping simon.foo (99 documents)
2020-10-25T12:24:21.809+0800	done dumping test.t2 (1 document)
2020-10-25T12:24:21.809+0800	done dumping test.t3 (1 document)
2020-10-25T12:24:21.809+0800	done dumping test.t1 (19 documents)
2020-10-25T12:24:21.810+0800	writing captured oplog to 
2020-10-25T12:24:21.810+0800		dumped 1 oplog entry
[mongod@mysql-node01 backup]$



再次模拟数据
use simon_db
db.t2.insert({id:1})
db.t3.insert({id:2})


2、上午10点:删除wo库下的ci表
10:00时刻,误删除
my_repl:PRIMARY> db.t1.drop()
true
my_repl:PRIMARY>
my_repl:PRIMARY> show tables
t2
t3
my_repl:PRIMARY>

3、备份现有的oplog.rs表
mongodump --port 28017 -d local -c oplog.rs  -o /mongodb/backup/oplog
[mongod@mysql-node01 opdata]$ mongodump --port 28017 -d local -c oplog.rs -o /mongodb/backup/oplog
2020-10-25T12:27:25.481+0800	writing local.oplog.rs to 
2020-10-25T12:27:25.488+0800	done dumping local.oplog.rs (2508 documents)
[mongod@mysql-node01 opdata]$
[mongod@mysql-node01 local]$ cd /mongodb/backup/oplog/

[mongod@mysql-node01 oplog]$ ll local/
total 292
-rw-rw-r-- 1 mongod mongod 293813 Oct 25 12:27 oplog.rs.bson
-rw-rw-r-- 1 mongod mongod    125 Oct 25 12:27 oplog.rs.metadata.json
[mongod@mysql-node01 oplog]$

4、截取oplog并恢复到drop之前的位置
更合理的方法:登陆到原数据库
[mongod@mysql-node01 oplog]$ mongo --port 28017
my_repl:PRIMARY> use local
my_repl:PRIMARY> db.oplog.rs.find({"op":"c"}).pretty()

{
	"ts" : Timestamp(1603599960, 1),
	"t" : NumberLong(2),
	"h" : NumberLong("3370511625250650296"),
	"v" : 2,
	"op" : "c",
	"ns" : "simon_db.$cmd",
	"ui" : UUID("9d0650c5-cba0-4747-ad30-4195b5204aa3"),
	"wall" : ISODate("2020-10-25T04:26:00.989Z"),
	"o" : {
		"drop" : "t1"
	}
}


获取到oplog误删除时间点位置:
"ts" : Timestamp(1603599960, 1)

 5、恢复备份+应用oplog
 # 挪走备份时间点的oplog
[mongod@mysql-node01 opdata]$ mv oplog.bson /tmp/

# 把刚才导出的oplog信息cp到全备文件
[mongod@mysql-node01 opdata]$ cd /mongodb/backup/oplog/local/
[mongod@mysql-node01 local]$ ls
oplog.rs.bson  oplog.rs.metadata.json
[mongod@mysql-node01 local]$
[mongod@mysql-node01 local]$ cp oplog.rs.bson /mongodb/backup/opdata/oplog.bson
[mongod@mysql-node01 local]$ ll /mongodb/backup/opdata/
total 288
drwxrwxr-x 2 mongod mongod     69 Oct 25 12:24 admin
-rw-rw-r-- 1 mongod mongod 293813 Oct 25 12:36 oplog.bson
drwxrwxr-x 2 mongod mongod     47 Oct 25 12:24 simon
drwxrwxr-x 2 mongod mongod     45 Oct 25 12:24 simon_db
drwxrwxr-x 2 mongod mongod    123 Oct 25 12:24 test
[mongod@mysql-node01 local]$

 
mongorestore --port 28017  --oplogReplay --oplogLimit "1603599960:1"  --drop   /mongodb/backup/opdata/

# --oplogLimit "1603599960:1" 只恢复指定的时间戳之前的记录

# 这里是测试环境,所以加了--drop参数,删除库里的原集合,再重新创建
# 生产环境,要用备份恢复到非生产环境节点,再把要恢复的数据导出导入到线上

[mongod@mysql-node01 local]$ mongorestore --port 28017 --oplogReplay --oplogLimit "1603599960:1" --drop /mongodb/backup/opdata/
2020-10-25T12:39:02.021+0800	preparing collections to restore from
2020-10-25T12:39:02.022+0800	reading metadata for simon.foo from /mongodb/backup/opdata/simon/foo.metadata.json
2020-10-25T12:39:02.023+0800	reading metadata for simon_db.t1 from /mongodb/backup/opdata/simon_db/t1.metadata.json
2020-10-25T12:39:02.024+0800	reading metadata for test.t1 from /mongodb/backup/opdata/test/t1.metadata.json
2020-10-25T12:39:02.031+0800	restoring simon.foo from /mongodb/backup/opdata/simon/foo.bson
2020-10-25T12:39:02.041+0800	restoring test.t1 from /mongodb/backup/opdata/test/t1.bson
2020-10-25T12:39:02.042+0800	reading metadata for test.t2 from /mongodb/backup/opdata/test/t2.metadata.json
2020-10-25T12:39:02.045+0800	restoring simon_db.t1 from /mongodb/backup/opdata/simon_db/t1.bson
2020-10-25T12:39:02.055+0800	restoring test.t2 from /mongodb/backup/opdata/test/t2.bson
2020-10-25T12:39:02.074+0800	no indexes to restore
2020-10-25T12:39:02.074+0800	finished restoring simon_db.t1 (19 documents)
2020-10-25T12:39:02.075+0800	reading metadata for test.t3 from /mongodb/backup/opdata/test/t3.metadata.json
2020-10-25T12:39:02.075+0800	no indexes to restore
2020-10-25T12:39:02.075+0800	finished restoring simon.foo (99 documents)
2020-10-25T12:39:02.082+0800	restoring test.t3 from /mongodb/backup/opdata/test/t3.bson
2020-10-25T12:39:02.084+0800	no indexes to restore
2020-10-25T12:39:02.084+0800	finished restoring test.t1 (19 documents)
2020-10-25T12:39:02.084+0800	no indexes to restore
2020-10-25T12:39:02.084+0800	finished restoring test.t2 (1 document)
2020-10-25T12:39:02.092+0800	no indexes to restore
2020-10-25T12:39:02.092+0800	finished restoring test.t3 (1 document)
2020-10-25T12:39:02.092+0800	replaying oplog
2020-10-25T12:39:02.187+0800	done
[mongod@mysql-node01 local]$

# 登陆MongoDB查看
[mongod@mysql-node01 local]$ mongo --port 28017
my_repl:PRIMARY> 
my_repl:PRIMARY> 
my_repl:PRIMARY> use simon_db
switched to db simon_db
my_repl:PRIMARY> show tables
t1
t2
t3
my_repl:PRIMARY> 
my_repl:PRIMARY> db.t1.count()
19
my_repl:PRIMARY>

扩展命令:

https://docs.mongodb.com/v3.6/reference/program/bsondump/

bsondump 可以将bson格式的数据转换成json

然后用mongoimport 导入

[mongod@mysql-node01 local]$ bsondump oplog.rs.bson

分片集群的备份思路(了解)

方案一:社区版 直接通过mongos进行备份。

mongos可以进行完整备份,只能对单一节点进行恢复。如果是两个shard分片节点,那就相当于要推倒shard节点进行重构。

方案二:企业版(收费),专门的备份工具,Ops manager,可以对单一分片、集群当中的所有关键节点进行备份。还可以实现部分恢复

方案三:自己开发分布式备份系统

尽管理论上我们可以使用与复制集同样的方式来为分片集完成增量备份,但实际上分片集的情况更加复杂。这种复杂性来自两个方面:

  • 各个数据节点的时间不一致:每个数据节点很难完全恢复到一个真正的一致时间点上,通常只能做到大致一致,而这种大致一致通常足够好,除了以下情况;
  • 分片间的数据迁移:当一部分数据从一个片迁移到另一个片时,最终数据到底在哪里取决于config中的元数据。如果元数据与数据节点之间的时间差异正好导致数据实际已经迁移到新分片上,而元数据仍然认为数据在旧分片上,就会导致数据丢失情况发生。虽然这种情况发生的概率很小,但仍有可能导致问题。

要避免上述问题的发生,只有定期停止均衡器;只有在均衡器停止期间,增量恢复才能保证正确。

1、你要备份什么?
config server
shard 节点

单独进行备份
2、备份有什么困难和问题
(1)chunk迁移的问题
    人为控制在备份的时候,避开迁移的时间窗口
(2)shard节点之间的数据不在同一时间点。
    选业务量较少的时候,把configserver,各个shard节点摘除从节点。

关于备份分片集群,官方给出的思路:
1、stop Balancer(and w ait)	# 停止balancer
2、or no balancing window   # 或者开启一个没有balancing的空窗口 
3、stop on config server、Shard node (data R/O) # 停掉一个configserver和shard node
4、backup data (shards,config) # 备份shards、config 数据
5、restart config server、shard node # 再把节点加入到MSC集群
6、Resume balancer

恢复:
1、Dissmilar #shards to restore to 
2、Different shard keys?
3、selective restores
4、consolidate shards
5、changing addresses of config/shards

Ops Manager 

标签:10,mongod,--,MongoDB,0800,oplog,2020,OpLog
来源: https://www.cnblogs.com/oldSimon/p/16290813.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有