背景:

原来一个同事问我主从mongodb数据库为什么数据差距很大,我让他察看一下两边有啥不一样,发现

主的local库有13G从却很小,进入local之后du发现有一个collection前缀的文件有13g,说明是local数据库中一个集合太大了,推测是oplog太大了,oplog是类似于mysql的binlog oracle的archivelog

当Primary进行写操作的时候,会将这些写操作记录写入Primary的Oplog中,而后Secondary会将Oplog复制到本机并应用这些操作,从而实现Replication的功能。同时由于其记录了Primary上的写操作,故还能将其用作数据恢复。可以简单的将其视作Mysql中的binlog。

为了进一步确认,进入mongodb之后通过

show dbs

use local

show collections

看到现有的集合

然后

db.getReplicationInfo()

rs.printReplicationInfo()

了解一下复制信息以及oplog大小与使用情况

为进一步确认相应的文件是否为oplog

db.printCollectionStats()

根据展示出来的结果只需要知道两条信息:

"ns" : "local.oplog.$main",

"uri" : "statistics:table:local/collection-2-1716662444632575459"

就可以确认oplog集合的相应文件,oplog如果太大可以清理和修改大小。

MongoDB oplog是一个capped collection,创建capped collection时,createCollection可以设置size(最大字节数)和max(最大文档数)的参数,当这个集合的『总大小超过size』或者『总文档数超过max』时,在新插入文档时就会自动删除一些集合内最先插入的文档,相当于一片环形的存储空间。

oplog(local.oplog.rs集合)默认情况下配置为可用磁盘空间的5%,当oplog写满时,就会开始删除最先写入的oplog,一次正常的insert操作包含如下步骤:将文档写入指定的集合

将写入操作记录到oplog

如果oplog满了,删除最先写入的oplog

优化策略

MongoDB 3.2为了提升写入性能,使用wiredtiger引擎时,针对local.oplog.rs这个集合的删除策略进行了优化,主要改进:将删除动作从用户的写入路径移除,放到后台线程执行

批量删除,并不是oplog一满就立马触发删除,而是一次删除一批

实施方案

monogd启动时,会根据oplog的最大字节数将整个集合分为10-100个Stone(可以理解为oplog的一段数据,包含多个文档,Stone的具体个数oplogSizeMB的配置相关)。WiredTigerRecordStore::OplogStones::OplogStones(OperationContext* txn, WiredTigerRecordStore* rs)

: _rs(rs) {

//...

unsigned long long maxSize = rs->cappedMaxSize();

const unsigned long long kMinStonesToKeep = 10ULL;

const unsigned long long kMaxStonesToKeep = 100ULL;

unsigned long long numStones = maxSize / BSONObjMaxInternalSize;

_numStonesToKeep = std::min(kMaxStonesToKeep, std::max(kMinStonesToKeep, numStones));

_minBytesPerStone = maxSize / _numStonesToKeep;

// ...

}

其中_numStonesToKeep为oplog应该保持的Stone个数,而_minBytesPerStone代表每个Stone的最小字节数。

接下来,会根据oplog当前的大小以及_minBytesPerStone来估算下,当前的oplog大致包含的Stone数量,并通过采样的方式来获取每个Stone的起始位置(不能保证每个Stone的大小跟预期完全一样),然后将所有的Stone按顺序存储到一个队列中。

mongod在服务写请求的过程中,每次都会记录下新产生oplog的大小,当新产生的oplog的总量超过_minBytesPerStones时,就会产生一个新的Stone加入到队列中。void WiredTigerRecordStore::OplogStones::createNewStoneIfNeeded(RecordId lastRecord) {

if (_currentBytes.load() < _minBytesPerStone) {

// Must have raced to create a new stone, someone else already triggered it.

return;

}

// ...

OplogStones::Stone stone = {_currentRecords.swap(0), _currentBytes.swap(0), lastRecord};

_stones.push_back(stone);

_pokeReclaimThreadIfNeeded(); // 唤醒后台回收oplog空间的线程

}

当队列中的Stone数量超过_numStonesToKeep,后台线程就会删除最老的Stone里的数据,来回收oplog的存储空间。

修改mongodb oplog size

oplog简介:

oplog:operations log的简写,存储在一个特殊的数据库中(local),oplog就存储在其中的oplog.$main集合里面,这个集合是一个固定集合,新操作会自动替换旧的操作,以保证oplog不会超过预设的大小,其中的每个文档都代表主节点上执行的一个操作,oplog会包含所有对数据有修改的的操作(查询操作不会记录),默认下,oplog大小会占用64位的实例5%的可用磁盘空间。

mongo复制的过程:主节点应用业务操作修改到数据库中,然后记录这些操作到oplog中,从节点复制这些oplog,然后应用这些修改。ps:这些操作是异步的。如果从节点的操作已经被主节点落下很远,oplog日志在从节点还没执行完,oplog可能已经轮滚一圈了,从节点跟不上同步,复制就会停下,从节点需要重新做完整的同步,为了避免此种情况,尽量保证主节点的oplog足够大,能够存放相当长时间的操作记录。

查询oplog的大小及保存的操作记录持续的时长

repltest:PRIMARY> db.printReplicationInfo()

configured oplog size:   1024MB

log length start to end: 3705secs (1.03hrs)

oplog first event time:  Thu Oct 10 2013 11:13:29 GMT+0800 (CST)

oplog last event time:   Thu Oct 10 2013 12:15:14 GMT+0800 (CST)

now:                     Fri Oct 11 2013 16:33:42 GMT+0800 (CST)

查询从节点的数据源列表,其中有数据滞后的时间

repltest:PRIMARY> db.printSlaveReplicationInfo()

source:   192.168.1.101:37017

syncedTo: Fri Oct 11 2013 16:38:16 GMT+0800 (CST)

= 1 secs ago (0hrs)

source:   192.168.1.100:37017

no replication info, yet.  State: ARBITER

so,修改oplog的大小:(下面介绍两种方式)

方式一:

The oplog exists internally as a capped collection, so you cannot modify its size in the course of normal operations.另:改变oplog大小,需要在每个节点上执行维护模式。(官方推荐)

步骤:

1:重启一个实例以单机模式,

通常再关闭server之前,使用rs.stepDown() 强制primary成为secondary

2:重新创建一个新大小,

其中包含旧的oplgo的入口条目的oplog

3:重启mongod作为replica set的成员

操作步骤:

1>: Restart a Secondary in Standalone Mode on a Different Port

关闭mongod实例:

repset:PRIMARY> use admin

repset:PRIMARY> db.shutdownServer()

重启mongod实例以单机模式,修改端口,并不要加--replSet参数

#vim /etc/mongo.conf

dbpath=/var/lib/mongodb

logpath=/var/log/mongodb/mongo.log

pidfilepath=/var/run/mongo.pid

directoryperdb=true

logappend=true

#replSet=repset

bind_ip=192.168.1.100,127.0.0.1

port=37017

oplogSize=2000

fork=true# mongod -f /etc/mongo.conf

备份oplog# mongodump --db local --collection 'oplog.rs' --port 37017

2>: Recreate the Oplog with a New Size and a Seed Entry

保存oplog的最新的时间点

> use local

> db.temp.save( db.oplog.rs.find( { }, { ts: 1, h: 1 } ).sort( {$natural : -1} ).limit(1).next() )

> db.temp.find()

删除旧的oplog

> db.oplog.rs.drop()

3> :Create a New Oplog

创建一个新的Oplog,大小为2G

> db.runCommand( { create: "oplog.rs", capped: true, size: (2 * 1024 * 1024 * 1024) } )

插入前面保存的旧的oplog的时间点的记录

> db.oplog.rs.save( db.temp.findOne() )

> db.oplog.rs.find()

4>:Restart the Member:

关闭单机实例:

> use admin

> db.shutdownServer()

修改回配置# vim /etc/mongo.conf

dbpath=/var/lib/mongodb

logpath=/var/log/mongodb/mongo.log

pidfilepath=/var/run/mongo.pid

directoryperdb=true

logappend=true

replSet=repset

bind_ip=192.168.1.100,127.0.0.1

port=37017

oplogSize=2000

fork=true

启动mongod

# mongod -f /etc/mongo.conf

重复上述步骤到所有需要更改的节点。

方式二:

步骤:

1:停掉所有replca set节点.

2:主节点删除local库下的文件,从节点删除数据目录下所有文件.

3:修改所有节点配置文件.

4:重启所有节点.

5:重新配置replca set,从节点会重新同步所有数据(initial sync).

ps:此法好处是简单,但需要停掉服务,且如果数据量很大,初始同步的成本较高

1>:关闭mongod实例(所有节点)

> use admin

> db.shutdownServer()

2>:删除local数据库下的所有文件(PRIMARY节点)

# rm -rf /var/lib/mongodb/local/*

删除mongo数据目录(其他节点上操作,可不要删错哦,建议所有rm操作先mv,待无问题时候再删除)# rm -rf /var/lib/mongodb/*

3> 修改所有节点配置文件(oplogsize)

# vim /etc/mongo.conf

dbpath=/var/lib/mongodb

logpath=/var/log/mongodb/mongo.log

pidfilepath=/var/run/mongo.pid

directoryperdb=true

logappend=true

replSet=repset

bind_ip=192.168.1.100,127.0.0.1

port=37017

oplogSize=2000

fork=true

4> 重启所有节点mongod

> mongod -f /etc/mongo.conf

mysql binlog oplog_mongodb 学习之oplog相关推荐

  1. Mysql binlog应用场景与原理深度剖析

    1 基于binlog的主从复制 Mysql 5.0以后,支持通过binary log(二进制日志)以支持主从复制.复制允许将来自一个MySQL数据库服务器(master) 的数据复制到一个或多个其他M ...

  2. mysql binlog 多少,MySQL binlog后面的编号最大是多大?

    在上课中讲到MySQL的binlog是mysql-bin.000001,有细心的学习提到,是不是这个达到mysql-bin.999999后数据库的binlog就要重新开始了? 对于这个问题一时间也被问 ...

  3. 好文推荐 | MySQL binlog应用场景与原理深度剖析

    作者:田守枝 来自:田守枝的博客(公众号) 本文深入介绍Mysql Binlog的应用场景,以及如何与MQ.elasticsearch.redis等组件的保持数据最终一致.最后通过案例深入分析binl ...

  4. mysql binlog 回退_MYSQL Binglog分析利器:binlog2sql使用详解

    大部分使用mysql的业务也都会开启binlog,用以记录数据库的更新操作.当然binlog的格式大家也都比较清楚,分别是statement.mixed.row模式.针对row格式的binlog,它以 ...

  5. mysql binlog解析 c_解析MYSQL BINLOG二进制格式(9)--infobin解析binlog帮助文档

    原创:转载请说明出处谢谢! 上接 http://blog.itpub.net/7728585/viewspace-2133188/ 解析MYSQL BINLOG 二进制格式(1)--准备工作 http ...

  6. mysql binlog ignore db_MySQL binlog_ignore_db 参数的具体使用

    前言: 经过前面文章学习,我们知道 binlog 会记录数据库所有执行的 DDL 和 DML 语句(除了数据查询语句select.show等).注意默认情况下会记录所有库的操作,那么如果我们有另类需求 ...

  7. MySQL binlog 数据恢复

    不求人,MySQL Binlog数据恢复 文章目录 不求人,MySQL Binlog数据恢复 浅谈恢复形式 开启 binlog 及配置 删库跑路(搭建测试数据库,然后删除它) 起死回生(分析binlo ...

  8. B站《一天学会 MySQL 数据库》学习笔记

    B站<一天学会 MySQL 数据库>学习笔记 老司机带我飞 职场十字诀:思考.计划.行动.总结.反思 ​关注他 4 人赞同了该文章 登录和退出MySQL服务器 # 登录MySQL $ my ...

  9. Mysql binlog日志及binlog恢复数据库操作

    初识MySQL 日志binlog MySQL重要log,二进制日志文件,记录所有DDL和DML语句(除select),事件形式记录,包含语句所执行的消耗时间,事务安全型. DDL(数据库定义语言),主 ...

最新文章

  1. Linux那些事儿 之 戏说USB(14)端点
  2. VMWare虚拟机网络连接
  3. 树言树语:谁动了苹果的弦
  4. 如何在Django中以GROUP BY查询?
  5. Linux 中模拟延时和丢包的实现
  6. 百度地图android自定义文字,androidsdk | 百度地图API SDK
  7. python 中__name__ = '__main__' 的作用
  8. CSP认证201809-2 买菜[C++题解]:区间覆盖、pair、交集长度、右端点的min-左端点的max
  9. sqlserver循环like变量_numba从入门到精通(6)—numba与循环与并行
  10. java中抽象类继承抽象类_Java中的抽象类用示例解释
  11. 百度-北大在Kaggle发起自动驾驶环境下的汽车6-DOF预测挑战赛
  12. hdu 1025 Constructing Roads In JGShining's Kingdom(DP + 二分)
  13. 解决UnicodeEncodeError: 'ascii' codec can't encode characters in position 问题(转)
  14. iOS资源大全中文版
  15. 参考文献标引方式_参考文献的标注方法
  16. Arduino 控制 DS1302 时钟芯片
  17. Mutual Component Convolutional Neural Networks for Heterogeneous Face Recognition阅读笔记
  18. 米老师经典语录————再造生命力
  19. 在编程中常见的一些英语词汇
  20. L298N双路驱动直流电机方案(支持PWM+正反转)

热门文章

  1. C# 8中的范围类型(Range Type)
  2. 在碰撞中成长 - 北京银行的DevOps实践之路
  3. 关于负载均衡的一切:总结与思考
  4. 你真的理解CAP理论吗?
  5. 在.NET Core 上运行的 WordPress
  6. 一款全新的基于IntelliJ和ReSharper的跨平台.NET IDE
  7. ASP.NET Core 启动方式(Hosting)
  8. .NET跨平台实践:用C#开发Linux守护进程
  9. Windows 下 Redis 的下载和安装
  10. Struts2中的OGNL表达式