返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >mongodb中oplog介绍和格式详析
  • 680
分享到

mongodb中oplog介绍和格式详析

2024-04-02 19:04:59 680人浏览 泡泡鱼
摘要

目录1. 基本概念 2. Oplog 的默认储存大小 3. 可能需要更大oplog的工作负载 4. Oplog状态 5. Oplog格式 6. CUD操作和Oplog的对应关系 de

1. 基本概念

    oplog使用固定大小集合记录了数据库中所有修改操作的操作日志(新增、修改和删除,无查询),mongoDB收到修改请求后,先在主节点(Primary)执行请求,再把操作日志保存到oplog表中,其他从节点(Secondary)到主节点拉取oplog并在异步进程中应用这些操作,从而达到主从数据的一致性。复制组内的所有节点都会保存一份oplog(集合名local.oplog.rs),这让他们可以保持同样的数据库状态。

    为了提高同步效率,所有复制组成员都会向其他成员发送保活报文(pings),任意从节点可以从其他成员节点同步oplog(即可以从主节点同步,也可以从从节点同步)。oplog中的操作都是幂等的,即oplog中的某个操作日志在目标数据库中应用一次或者多次,其结果都是一样的。

    主从同步示意图如下(客户端写数据到主节点,从节点从主节点同步oplog并应用到本节点):

2. Oplog 的默认储存大小

 当你首次启动复制组节点时,在你未指定oplog大小时,monGodb会使用默认大小来创建oplog。

对于Unix和windows系统来说,默认大小和存储引擎的对应关系如下:

存储引擎类型 oplog大小 下限 上限
内存 物理内存的5% 50MB 50GB
WiredTiger 空闲磁盘的5% 990MB 50GB 

 (注意,最新4.4版本的mongodb移除了MMAP类型存储引擎的支持。)

对于64位maxOS系统来说,参照使用的存储引擎类型,该默认大小是192MB(物理内存或者磁盘空间),如下:

存储引擎类型 oplog大小
内存 192MB物理内存
WiredTiger 192MB的磁盘空间

大部分情况下,oplog的默认大小是足够的。举个例子,如果5%的磁盘空间存储了最近24小时的操作日志,此时如果某个从节点的日志同步时间差超过24小时时,从节点将停止同步oplog,并将自身的状态从“Secondery”切换到“STALE”。当然,在实际的运行环境中,大部分复制组成员的负载会低一些,他们的oplog中也会持有更长时间段的日志。

3. 可能需要更大oplog的工作负载

如果你预测到你的复制组的工作负载属于以下的模式,你需要创建比默认值更大一些的oplog。相反的,如果你的应用大部分情况下是读操作,只有小部分的写操作,那么更小一些的oplog也是满足需要的。

下面的工作负载可能需要更大一些的oplog

单次操作会更新多条记录

为了满足oplog的幂等性,单次操作更新多条记录时,mongodb会记录多条操作日志到oplog中,这种场景就需要使用大量的oplog的空间,虽然此时数据大小或者磁盘大小并没有相应的增加那么多。

删除操作和插入操作一样多时

 如果你的删除操作请求量和插入操作的请求量大致相当时,数据库在磁盘空间消耗方面不会有明显增长,但是操作日志的大小会非常巨大。

显著数量的原文档更新

如果工作负载的大部分操作都是原文档更新,此时虽然不会增加数据库中文档的数量,但是数据库需要记录大量的操作日志。

4. Oplog状态

如果要查看oplog的状态,包含记录条数和时间范围,可以使用"rs.printReplicationInfo() "命令,如下:


MongoDB Enterprise repa:PRIMARY> rs.printReplicationInfo()
configured oplog size:   1024MB  // oplog大小是1024MB
log length start to end: 867353secs (240.93hrs)  // 第一条和最后一条日志的时间差是240.93小时
oplog first event time:  Wed Jul 07 2021 20:24:57 GMT+0800
oplog last event time:   Sat Jul 17 2021 21:20:50 GMT+0800
now:                     Sat Jul 17 2021 21:20:56 GMT+0800

5. Oplog格式

从前面知道oplog是存储在数据库local中,表名为“oplog.rs”,通过查询命令看一下oplog的数据格式:


db.oplog.rs.find({"ns":"test.users"}).limit(1)   // ns字段指明查询对数据库test中users表的操作日志
{
    "ts": Timestamp(1625660877, 2),     // 日志的操作时间戳,第一个数字是时间戳,单位秒,第二个数字是当前秒的第2个操作
    "t": NumberLong(2),
    "h": NumberLong("5521980394145765083"),
    "v": 2,
    "op": "i",            // i表示insert,u表示update,d表示delete,c 表示的是数据库的命令,比如建表,n表示noop,即空操作
    "ns": "test.users",   // 命名空间,即数据库和集合名称
    "ui": UUID("edabbd93-76eb-42be-b54a-cdc29eb1f267"), // 连接到mongodb的客户端会话id
    "wall": ISODate("2021-07-07T12:27:57.689Z"),  // 操作执行时间,utc时间
    "o": {        // 操作的内容,对于不同的op类型,其格式不尽相同
        "_id": ObjectId("60e59dcd46db1fb4605f8b18"),
        "name": "1"
    }
}

6. CUD操作和Oplog的对应关系

前面分析oplog日志格式的时候,查看了一条insert操作对应的日志,就不再赘述,下面再看下delete和update对应的日志格式(find不会产生oplog)。

delete操作

首先插入三条记录:


MongoDB Enterprise repa:PRIMARY> use testswitched to db testMongoDB Enterprise repa:PRIMARY> db.users.insert({"name":"张三","age":NumberInt(10),"sex":"男"})WriteResult({ "nInserted" : 1 })MongoDB Enterprise repa:PRIMARY> db.users.insert({"name":"李四","age":NumberInt(11),"sex":"男"})WriteResult({ "nInserted" : 1 })MongoDB Enterprise repa:PRIMARY> db.users.insert({"name":"王五","age":NumberInt(12),"sex":"男"})WriteResult({ "nInserted" : 1 })MongoDB Enterprise repa:PRIMARY> db.users.find(){ "_id" : ObjectId("60f2e11b0d98dc3b374199de"), "name" : "张三", "age" : 10, "sex" : "男" }{ "_id" : ObjectId("60f2e11e0d98dc3b374199df"), "name" : "李四", "age" : 11, "sex" : "男" }{ "_id" : ObjectId("60f2e11e0d98dc3b374199e0"), "name" : "王五", "age" : 12, "sex" : "男" }

执行delete操作,匹配条件是{"sex":"男"},即删除所有性别为男的记录:


MongoDB Enterprise repa:PRIMARY> db.users.remove({"sex":"男"})
WriteResult({ "nRemoved" : 3 })
MongoDB Enterprise repa:PRIMARY> db.users.find()
MongoDB Enterprise repa:PRIMARY>

可以看到,一条删除命令删除了三条记录,对应的oplog是什么呢,来,查一下:


MongoDB Enterprise repa:PRIMARY> use local
switched to db local
MongoDB Enterprise repa:PRIMARY> db.oplog.rs.find({"ns":"test.users","op":"d","wall":{"$gt":ISODate("2021-07-17T13:50:57.689Z")}})
{ "ts" : Timestamp(1626530154, 1), "t" : NumberLong(2), "h" : NumberLong("5834731856459959506"), "v" : 2, "op" : "d", "ns" : "test.users", "ui" : UUID("edabbd93-76eb-42be-b54a-cdc29eb1f267"), "wall" : ISODate("2021-07-17T13:55:54.424Z"), "o" : { "_id" : ObjectId("60f2e11b0d98dc3b374199de") } }
{ "ts" : Timestamp(1626530154, 2), "t" : NumberLong(2), "h" : NumberLong("-2164276082472824844"), "v" : 2, "op" : "d", "ns" : "test.users", "ui" : UUID("edabbd93-76eb-42be-b54a-cdc29eb1f267"), "wall" : ISODate("2021-07-17T13:55:54.424Z"), "o" : { "_id" : ObjectId("60f2e11e0d98dc3b374199df") } }
{ "ts" : Timestamp(1626530154, 3), "t" : NumberLong(2), "h" : NumberLong("3834858247238363179"), "v" : 2, "op" : "d", "ns" : "test.users", "ui" : UUID("edabbd93-76eb-42be-b54a-cdc29eb1f267"), "wall" : ISODate("2021-07-17T13:55:54.424Z"), "o" : { "_id" : ObjectId("60f2e11e0d98dc3b374199e0") } }
MongoDB Enterprise repa:PRIMARY>

从上可以看到,一条删除命令,在oplog中记录了三条日志,下面分析其中的一条:


{
    "ts": Timestamp(1626530154, 1),
    "t": NumberLong(2),
    "h": NumberLong("5834731856459959506"),
    "v": 2,
    "op": "d",   // 删除操作
    "ns": "test.users",  // 数据库是test,集合是users
    "ui": UUID("edabbd93-76eb-42be-b54a-cdc29eb1f267"),
    "wall": ISODate("2021-07-17T13:55:54.424Z"),
    "o": {     // 待删除记录的_id
        "_id": ObjectId("60f2e11b0d98dc3b374199de")
    }
}

从上面日志分析可以得到结论:

用户的一次删除请求,如果删除了N条记录,那么oplog中将记录N条日志,日志中会记录待删除记录的“_id”字段,与用户的删除请求的参数无关。

update操作

下面再看下更新操作对应的oplog的日志数量和格式。

首先插入三条记录:


MongoDB Enterprise repa:PRIMARY> use test
switched to db test
MongoDB Enterprise repa:PRIMARY>
MongoDB Enterprise repa:PRIMARY> db.users.insert({"name":"张三","age":NumberInt(10),"sex":"男"})
WriteResult({ "nInserted" : 1 })
MongoDB Enterprise repa:PRIMARY> db.users.insert({"name":"李四","age":NumberInt(11),"sex":"男"})
WriteResult({ "nInserted" : 1 })
MongoDB Enterprise repa:PRIMARY> db.users.insert({"name":"王五","age":NumberInt(12),"sex":"男"})
WriteResult({ "nInserted" : 1 })
MongoDB Enterprise repa:PRIMARY> db.users.find()
{ "_id" : ObjectId("60f2e2db0d98dc3b374199e1"), "name" : "张三", "age" : 10, "sex" : "男" }
{ "_id" : ObjectId("60f2e2db0d98dc3b374199e2"), "name" : "李四", "age" : 11, "sex" : "男" }
{ "_id" : ObjectId("60f2e2dc0d98dc3b374199e3"), "name" : "王五", "age" : 12, "sex" : "男" }

再执行更新操作:


MongoDB Enterprise repa:PRIMARY> db.users.update({"sex":"男"},  {"$inc":{"age":NumberInt(1)}}, false, true)
WriteResult({ "nMatched" : 3, "nUpserted" : 0, "nModified" : 3 })
MongoDB Enterprise repa:PRIMARY> db.users.find()                                                          
{ "_id" : ObjectId("60f2e2db0d98dc3b374199e1"), "name" : "张三", "age" : 11, "sex" : "男" }
{ "_id" : ObjectId("60f2e2db0d98dc3b374199e2"), "name" : "李四", "age" : 12, "sex" : "男" }
{ "_id" : ObjectId("60f2e2dc0d98dc3b374199e3"), "name" : "王五", "age" : 13, "sex" : "男" }

从返回结果可以看到,更新操作执行成功,并更新了三条记录,下面看下oplog的日志:


MongoDB Enterprise repa:PRIMARY> use local
switched to db local
MongoDB Enterprise repa:PRIMARY> db.oplog.rs.find({"ns":"test.users","op":"u","wall":{"$gt":ISODate("2021-07-17T13:50:57.689Z")}})
{ "ts" : Timestamp(1626530575, 1), "t" : NumberLong(2), "h" : NumberLong("-6359278368726841648"), "v" : 2, "op" : "u", "ns" : "test.users", "ui" : UUID("edabbd93-76eb-42be-b54a-cdc29eb1f267"), "o2" : { "_id" : ObjectId("60f2e2db0d98dc3b374199e1") }, "wall" : ISODate("2021-07-17T14:02:55.319Z"), "o" : { "$v" : 1, "$set" : { "age" : 11 } } }
{ "ts" : Timestamp(1626530575, 2), "t" : NumberLong(2), "h" : NumberLong("-4351658862590633053"), "v" : 2, "op" : "u", "ns" : "test.users", "ui" : UUID("edabbd93-76eb-42be-b54a-cdc29eb1f267"), "o2" : { "_id" : ObjectId("60f2e2db0d98dc3b374199e2") }, "wall" : ISODate("2021-07-17T14:02:55.319Z"), "o" : { "$v" : 1, "$set" : { "age" : 12 } } }
{ "ts" : Timestamp(1626530575, 3), "t" : NumberLong(2), "h" : NumberLong("5911110003695351597"), "v" : 2, "op" : "u", "ns" : "test.users", "ui" : UUID("edabbd93-76eb-42be-b54a-cdc29eb1f267"), "o2" : { "_id" : ObjectId("60f2e2dc0d98dc3b374199e3") }, "wall" : ISODate("2021-07-17T14:02:55.319Z"), "o" : { "$v" : 1, "$set" : { "age" : 13 } } }

和delete类似,update操作也是产生了三条日志,选第一条分析:


{
    "ts": Timestamp(1626530575, 1),
    "t": NumberLong(2),
    "h": NumberLong("-6359278368726841648"),
    "v": 2,
    "op": "u",   // 更新操作
    "ns": "test.users",  // 数据库test,集合是users
    "ui": UUID("edabbd93-76eb-42be-b54a-cdc29eb1f267"),
    "o2": {  // 更新操作的查询条件,使用的记录的_id
        "_id": ObjectId("60f2e2db0d98dc3b374199e1")
    },
    "wall": ISODate("2021-07-17T14:02:55.319Z"),
    "o": {  // 更新操作的更新内容,原始的inc操作符转变为set操作符,可以满足幂等性
        "$v": 1,
        "$set": {
            "age": 11
        }
    }
}

从上面日志分析可以得到结论:

用户的一次更新请求,如果更新了N条记录,那么oplog中将记录N条日志,日志中记录待更新记录的“_id”字段为查询条件,更新操作使用的是set操作符,并不是用户的更新操作符。

小结

从上面的delete和update操作对应的oplog日志分析可以看出,oplog记录的不是用户的原始命令,而是对应的逻辑命令,通过这种方式可以满足oplog的幂等性,但是也会衍生出可能产生大量oplog记录的问题,需要用户根据业务模型的需要,来选择合适的oplog大小。

https://GitHub.com/tomliugen

总结

到此这篇关于mongodb中oplog介绍和格式详析的文章就介绍到这了,更多相关mongodb oplog和格式内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: mongodb中oplog介绍和格式详析

本文链接: https://lsjlt.com/news/130704.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • mongodb中oplog介绍和格式详析
    目录1. 基本概念 2. Oplog 的默认储存大小 3. 可能需要更大oplog的工作负载 4. Oplog状态 5. Oplog格式 6. CUD操作和Oplog的对应关系 de...
    99+
    2024-04-02
  • MongoDB Oplog中的字段介绍
    {     "ts" : Timestamp(1446011584, 2),         "h" : NumberLong("16873591...
    99+
    2024-04-02
  • mongodb中oplog的格式和作用是什么
    这篇文章主要讲解了“mongodb中oplog的格式和作用是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“mongodb中oplog的格式和作用是什么”吧!目录 基本概念 Oplog 的...
    99+
    2023-06-20
  • Mysql中Binlog3种格式的介绍与分析
    一.Mysql Binlog格式介绍      Mysql binlog日志有三种格式,分别为Statement,MiXED,以及ROW! 1.Statement:...
    99+
    2022-05-26
    mysqlbinlog参数 mysql binlog mysql binlog解析
  • C++中cout的格式使用详细介绍
    1.cout和i/i++/++i的组合使用 i++ 和 ++i 是有着不同的含义,和 cout 组合使用也会得到不同的结果,下面给出一段代码: #include <iost...
    99+
    2024-04-02
  • MySQL Binlog三种格式介绍及分析
    一.Mysql Binlog格式介绍 MySQL binlog日志有三种格式,分别为Statement,MiXED,以及ROW! 1.Statement:每一条会修改数据的sql都会记...
    99+
    2024-04-02
  • SpringBoot配置文件格式详细介绍
    目录一、application.properties配置文件二、yml和yaml配置文件配置格式(1)普通属性(2)数组属性(3)注意事项idea添加配置文件三、生效优先级一、app...
    99+
    2024-04-02
  • Python中字符串格式化str.format的详细介绍
    前言 Python 在 2.6 版本中新加了一个字符串格式化方法: str.format() 。它的基本语法是通过 {} 和 : 来代替以前的 %.。 格式化时的占位符语法: replacement_f...
    99+
    2022-06-04
    详细介绍 字符串 Python
  • MongoDB中4种日志的详细介绍
    前言 任何一种数据库都有各种各样的日志,MongoDB也不例外。MongoDB中有4种日志,分别是系统日志、Journal日志、oplog主从日志、慢查询日志等。这些日志记录着MongoDB数据库不同方面的...
    99+
    2024-04-02
  • Vue路由模式中的hash和history模式详细介绍
    目录1. 路由概念2. hash模式3. history路由模式1. 路由概念 路由的本质就是一种对应关系,根据不同的URL请求,返回对应不同的资源。那么url地址和真实的资源之间就...
    99+
    2024-04-02
  • Python的输出格式化和进制转换介绍
    目录复习输出格式化字符串如何进行格式化?进制转换思考题:总结Python输出格式化字符串如何进行格式化? 进制转换 复习 1.pycharm的使用 2.注释:单行、多行 3.变量:格...
    99+
    2024-04-02
  • Redis中GETBIT和SETBIT的详细介绍
    本篇内容介绍了“Redis中GETBIT和SETBIT的详细介绍”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所...
    99+
    2024-04-02
  • C++中模板和STL介绍详解
    目录一、模板1.1.函数模板1.1.1.两种函数模板的实例化1.1.2.模板参数的匹配原则1.2.类模板二、STL总结一、模板 对于一个交换函数,虽然C++支持函数重载,我们可以对多...
    99+
    2024-04-02
  • c++中string和vector的详细介绍
    目录知识点1【STL的概述】知识点2【迭代器的案例】知识点3【string类】1、案例:string的构造和赋值知识点1【STL的概述】 STL(Standard Template ...
    99+
    2024-04-02
  • Windows和linux系统文件合并命令格式介绍
    我们在Windows下实现文件合并,用"copy"命令就能实现: 格式:copy /b <filename1>+<filename2>+…+<filenam...
    99+
    2023-05-29
    Windows linux 合并 系统文件 命令
  • CSS table表格中tr和td的用法介绍
    本篇内容介绍了“CSS table表格中tr和td的用法介绍”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!...
    99+
    2024-04-02
  • 多线程中Future模式的详细介绍
    本篇内容介绍了“多线程中Future模式的详细介绍”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!在高性能编...
    99+
    2024-04-02
  • PHP中的工厂模式的详细介绍
    本篇内容主要讲解“PHP中的工厂模式的详细介绍”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“PHP中的工厂模式的详细介绍”吧!工厂模式是一种类,它具有为您创建对象的某些方法。您可以使用工厂类创建...
    99+
    2023-06-17
  • HTMl5的存储方式sessionStorage和localStorage的详细介绍
    本篇内容主要讲解“HTMl5的存储方式sessionStorage和localStorage的详细介绍”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“HTMl5的...
    99+
    2024-04-02
  • vue3的介绍和两种创建方式详解(cli和vite)
    目录一、vue3的介绍(一)vue3的简介(二)vue3对比vue2带来的性能提升 二、vue3的两种创建方式方式一:使用vue-cli创建(推荐--全面)操作步骤&nbs...
    99+
    2023-05-16
    vue3 cli和vite创建方式 vue3两种创建方式 vue3介绍
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作