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 的其他的文档没有什么不同,它固定有一些属性:
- ts: MongoDB 的内置的特殊时间戳数据结构,如 Timestamp(1503110518, 1), 由秒级的 Unix 时间戳和一个顺序增长的整数 increment 表示。长度为 64 位,其中 Unix 时间戳占 32 位,后 32 位可以保存同一秒内的第几次操作。
- h: hash 值代表每个 Oplog 的唯一标识。
- v: Oplog 版本
- ns: namespace 命名空间,数据库+集合,用 database.collection 表示。但如果是表操作命令等,变成 database.$cmd。
- op:operation type,操作类型,包含以下几种:
- i: insert, 插入文档
- u: update, 更新文档
- d: delete, 删除文档
- c: command, 操作命令,如 createIndex 等
- n: 空操作,用于空闲时主从同步 Oplog 时间信息
- o: operation, Oplog 操作的具体内容,例如 i operation type,o 即是插入的文档。对于 u operation type, 只更新部分内容, o 键的内容为 {$set: {...}}
- 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
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
免责声明:本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除!
《魔兽世界》大逃杀!60人新游玩模式《强袭风暴》3月21日上线
暴雪近日发布了《魔兽世界》10.2.6 更新内容,新游玩模式《强袭风暴》即将于3月21 日在亚服上线,届时玩家将前往阿拉希高地展开一场 60 人大逃杀对战。
艾泽拉斯的冒险者已经征服了艾泽拉斯的大地及遥远的彼岸。他们在对抗世界上最致命的敌人时展现出过人的手腕,并且成功阻止终结宇宙等级的威胁。当他们在为即将于《魔兽世界》资料片《地心之战》中来袭的萨拉塔斯势力做战斗准备时,他们还需要在熟悉的阿拉希高地面对一个全新的敌人──那就是彼此。在《巨龙崛起》10.2.6 更新的《强袭风暴》中,玩家将会进入一个全新的海盗主题大逃杀式限时活动,其中包含极高的风险和史诗级的奖励。
《强袭风暴》不是普通的战场,作为一个独立于主游戏之外的活动,玩家可以用大逃杀的风格来体验《魔兽世界》,不分职业、不分装备(除了你在赛局中捡到的),光是技巧和战略的强弱之分就能决定出谁才是能坚持到最后的赢家。本次活动将会开放单人和双人模式,玩家在加入海盗主题的预赛大厅区域前,可以从强袭风暴角色画面新增好友。游玩游戏将可以累计名望轨迹,《巨龙崛起》和《魔兽世界:巫妖王之怒 经典版》的玩家都可以获得奖励。
更新日志
- 小骆驼-《草原狼2(蓝光CD)》[原抓WAV+CUE]
- 群星《欢迎来到我身边 电影原声专辑》[320K/MP3][105.02MB]
- 群星《欢迎来到我身边 电影原声专辑》[FLAC/分轨][480.9MB]
- 雷婷《梦里蓝天HQⅡ》 2023头版限量编号低速原抓[WAV+CUE][463M]
- 群星《2024好听新歌42》AI调整音效【WAV分轨】
- 王思雨-《思念陪着鸿雁飞》WAV
- 王思雨《喜马拉雅HQ》头版限量编号[WAV+CUE]
- 李健《无时无刻》[WAV+CUE][590M]
- 陈奕迅《酝酿》[WAV分轨][502M]
- 卓依婷《化蝶》2CD[WAV+CUE][1.1G]
- 群星《吉他王(黑胶CD)》[WAV+CUE]
- 齐秦《穿乐(穿越)》[WAV+CUE]
- 发烧珍品《数位CD音响测试-动向效果(九)》【WAV+CUE】
- 邝美云《邝美云精装歌集》[DSF][1.6G]
- 吕方《爱一回伤一回》[WAV+CUE][454M]