Mongodb的oplog详解

 更新时间:2020年7月11日 17:02  点击:1671

Oplog 是 MongoDB 实现复制集的关键数据结构,在复制集中 Primary 对数据库操作之后就会产生一个 Oplog 文档保存在 local.oplog.rs 集合中,Secondary 成员会拉取 Primary 的 Oplog 并重放相同的操作,从而达到 Secondary 成员与 Primary 有一致的数据。实际上复制集中每一个成员都会保存 Oplog,其他成员会根据连接延迟等因数选择最近的成员拉取 Oplog 数据。

Oplog 存在集合 local.oplog.rs,这是系统内置集合,一个 capped collection,即是这个 collection 有固定大小,一旦写满数据会从头开始写入,就像一个圆形的队列结构。这个 collection 大小在初始化集群时设置,默认的大小是 5% 的空闲磁盘空间,也可以在配置文件设置 oplogSizeMB 选项,或者在启动 MongoDB 后使用 replSetResizeOplog 命令动态设置 collection 大小。

Oplog 与 MongoDB 的其他的文档没有什么不同,它固定有一些属性:

  1. ts: MongoDB 的内置的特殊时间戳数据结构,如 Timestamp(1503110518, 1), 由秒级的 Unix 时间戳和一个顺序增长的整数 increment 表示。长度为 64 位,其中 Unix 时间戳占 32 位,后 32 位可以保存同一秒内的第几次操作。
  2. h: hash 值代表每个 Oplog 的唯一标识。
  3. v: Oplog 版本
  4. ns: namespace 命名空间,数据库+集合,用 database.collection 表示。但如果是表操作命令等,变成 database.$cmd。
  5. op:operation type,操作类型,包含以下几种:
    1. i: insert, 插入文档
    2. u: update, 更新文档
    3. d: delete, 删除文档
    4. c: command, 操作命令,如 createIndex 等
    5. n: 空操作,用于空闲时主从同步 Oplog 时间信息
  6. o: operation, Oplog 操作的具体内容,例如 i operation type,o 即是插入的文档。对于 u operation type, 只更新部分内容, o 键的内容为 {$set: {...}}
  7. o2: 用于 update 操作,包含 _id 属性值。

Oplog 的重放是幂等(idempotent)的,即是说同一个 Oplog 重放多次最终结果还是一致的。这是 MongoDB 将许多命令操作进行了转化,保持生成的 Oplog 是可以幂等的,如执行以下 $inc 操作:

db.test.update({_id: ObjectId("533022d70d7e2c31d4490d22")}, {$inc: {count: 1}})

产生的 Oplog 为:

{
 "ts" : Timestamp(1503110518, 1),
 "t" : NumberLong(8),
 "h" : NumberLong(-3967772133090765679),
 "v" : NumberInt(2),
 "op" : "u",
 "ns" : "mongo.test",
 "o2" : {
  "_id" : ObjectId("533022d70d7e2c31d4490d22")
 },
 "o" : {
  "$set" : {
   "count" : 2.0
  }
 }
}

以上 MongoDB 可以保证 Oplog 的数据操作(DML 语句)是幂等的,但数据表操作(DDL 语句)命令无法保证,例如重复执行相同的 createIndex 命令。

Oplog 的查询

Capped collection 内文档是以插入顺序排序的,没有其他索引,但是 local.oplog.rs 是一个特殊的 capped collection,在 Wiredtiger 引擎的话,Oplog 的时间戳会作为一个特殊的元信息存储,使得 Oplog 可以以 ts 字段排序,查询 Oplog 时可以利用 ts 字段筛选。

一般来说 Secondary 同步需要经过 initial sync 和 incremental sync,initial sync 同步完成后,需拉取从同步时间点开始之后的 Oplog 进行持续重放。所以查询 Oplog 的操作一般是:

db.oplog.rs.find({$gte:{'ts': Timestamp(1503110518, 1)}})

Secondary 需要不断获取 Primary 产生的 Oplog, 复制集会使用 tailable cursor 持续获取 Oplog 数据,非常类似 Unix 系统的 tail -f。这会提高效率,因为一般的 cursor 使用完毕后就会关闭,而 tailable cursor 会保存上次的 id, 并持续获取数据。

如果使用 pymongo 驱动器,则定位从某个时间点之后的 Oplog 可以这麽写:

coll = db['local'].get_collection(
 'oplog.rs',
 codec_options=bson.codec_options.CodecOptions(document_class=bson.son.SON))

cursor = coll.find({'ts': {'$gte': start_optime}},
 cursor_type=pymongo.cursor.CursorType.TAILABLE,
 oplog_replay=True,
 no_cursor_timeout=True)

while True:
 try:
  oplog = cursor.next()
  process(oplog)
 except StopException:
  # 没有更多的 Oplog 数据
  time.sleep(1)

cursor_type 使用 TAILABLE 或者 TAILABLE_AWAIT,使用后一种类型时,如果没有更多的 Oplog 数据,则这次请求会阻塞等待有 Oplog 数据或者到达等待的时间超时返回。

设置 oplog_replay 标记可以表示此次请求的类型是保存 Oplog 的 capped collection, 提供 ts 筛选参数, 进行查询优化。

获取到 Oplog 之后,就可以做数据同步或者分发到感兴趣的消费者作特殊分析,如 MongoShake 工具。

参考了文档:

Replica Set Oplog: https://docs.mongodb.com/manual/core/replica-set-oplog/
MongoDB oplog 漫谈: http://caosiyang.github.io/2016/12/24/mongodb-oplog/
MongoDB复制集原理: https://www.jb51.net/article/166148.htm

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持猪先飞。

[!--infotagslink--]

相关文章

  • PHP添加MongoDB扩展实例教程

    由于要使用mikoomi mongodb plugin插件,所以需要php对mongodb的扩展支持,默认通过源安装的php并没有mongodb的扩展支持,具体可以通过php -m|grep mongo 验证 。这里就结...2016-11-25
  • 安装使用Mongoose配合Node.js操作MongoDB的基础教程

    这篇文章主要介绍了安装使用Mongoose来让Node.js操作MongoDB的基础教程,前端js+后端node+js操作MongoDB正是所谓最流行的一种JavaScript全栈开发方案,需要的朋友可以参考下...2016-03-03
  • mongodb与mysql命令详细对比

    传统的关系数据库一般由数据库(database)、表(table)、记录(record)三个层次概念组成,MongoDB是由数据库(database)、集合(collection)、文档对象(document)三个层次组成。MongoDB对于关系型数据库里的表,但是集合中没有列、行和关...2013-09-11
  • 修复 Mac brew 安装 mongodb 报 Error: No available formula with the name ‘mongodb’ 问题详解

    最近在同事新的 Mac 电脑上安装 mongodb,报了错误 Error: No available formula with the name ‘mongodb’,今天就说说这个问题如何解决,需要的朋友可以参考下...2020-07-11
  • MongoDb CPU利用率过高问题如何解决

    这篇文章主要介绍了MongoDb CPU利用率过高问题如何解决,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下...2020-12-08
  • Windows10安装MongoDB4.0详细步骤及启动配置教程

    这篇文章主要介绍了Windows10安装MongoDB4.0详细步骤及启动配置教程 ,本文通过图文并茂的形式给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下...2020-07-11
  • CentOS7.2 安装 MongoDB 3.4的教程

    这篇文章主要介绍了CentOS7.2 安装 MongoDB 3.4的方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2020-07-11
  • NestJs使用Mongoose对MongoDB操作的方法

    这篇文章主要介绍了NestJs使用Mongoose对MongoDB操作的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-02-22
  • MongoDB CRUD操作中的插入实例教程

    这篇文章主要给大家介绍了关于MongoDB CRUD操作中的插入的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用MongoDB具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧...2020-12-08
  • Navicat Premium连接mongodb详细教程

    这篇文章主要介绍了Navicat Premium连接mongodb详细教程,本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2021-03-05
  • MongoDB操作符中的$elemMatch问题

    这篇文章主要介绍了MongoDB操作符中的$elemMatch问题,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2020-07-11
  • Node+Express+MongoDB实现登录注册功能实例

    这篇文章主要介绍了Node+Express+MongoDB实现登录注册功能,需要的朋友可以参考下...2017-04-27
  • MongoDB中4种日志的详细介绍

    这篇文章主要给大家介绍了关于MongoDB中4种日志的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用MongoDB具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧...2020-07-11
  • Django项目连接MongoDB的三种方法

    本文主要介绍了Django项目连接MongoDB的三种方法,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2021-09-27
  • MongoDB 中聚合统计计算--$SUM表达式

    这篇文章主要介绍了MongoDB 中聚合统计计算--$SUM表达式的相关知识,本文通过实例代码给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下...2020-07-11
  • MongoDB多条件模糊查询示例代码

    这篇文章主要给大家介绍了关于MongoDB多条件模糊查询的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用MongoDB具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧...2020-07-11
  • c# 插入数据效率测试(mongodb)

    这篇文章主要介绍了c# 插入数据效率测试(mongodb),插入的速度要比Mysql和sqlserver都要快需要的朋友可以参考下...2020-06-25
  • dotnet core链接mongodb代码实例

    这篇文章主要介绍了dotnet core链接mongodb代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下...2020-06-25
  • 详解Wondows下Node.js使用MongoDB的环境配置

    这篇文章主要介绍了详解Wondows下Node.js使用MongoDB的环境配置,这里使用到了Mongoose驱动来让JavaScript操作MongoDB,需要的朋友可以参考下...2016-03-03
  • 分布式文档存储数据库之MongoDB备份与恢复的实践详解

    这篇文章主要介绍了分布式文档存储数据库之MongoDB备份与恢复,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2020-12-08