日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

MongoDB 定位 oplog 必须全表扫描吗?

發布時間:2024/8/23 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 MongoDB 定位 oplog 必须全表扫描吗? 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

MongoDB oplog (類似于 MySQL binlog) 記錄數據庫的所有修改操作,除了用于主備同步;oplog 還能玩出很多花樣,比如

  • 全量備份 + 增量備份所有的 oplog,就能實現 MongoDB 恢復到任意時間點的功能
  • 通過 oplog,除了實現到備節點的同步,也可以額外再往單獨的集群同步數據(甚至是異構的數據庫),實現容災、多活等場景,比如阿里云開源的 MongoShake?就能實現基于 oplog 的增量同步。
  • MongoDB 3.6+ 版本對 oplog 進行了抽象,提供了?Change Stream?的接口,實際上就是能不斷訂閱數據庫的修改,基于這些修改可以觸發一些自定義的事件。
  • ......
  • 總的來說,MongoDB 可以通過 oplog 來跟生態對接,來實現數據的同步、遷移、恢復等能力。而在構建這些能力的時候,有一個通用的需求,就是工具或者應用需要有不斷拉取 oplog 的能力;這個過程通常是

  • 根據上次拉取的位點構建一個 cursor
  • 不斷迭代 cursor 獲取新的 oplog
  • 那么問題來了,由于 MongoDB oplog 本身沒有索引的,每次定位 oplog 的起點都需要進行全表掃描么?

    oplog 的實現細節

    { "ts" : Timestamp(1563950955, 2), "t" : NumberLong(1), "h" : NumberLong("-5936505825938726695"), "v" : 2, "op" : "i", "ns" : "test.coll", "ui" : UUID("020b51b7-15c2-4525-9c35-cd50f4db100d"), "wall" : ISODate("2019-07-24T06:49:15.903Z"), "o" : { "_id" : ObjectId("5d37ff6b204906ac17e28740"), "x" : 0 } } { "ts" : Timestamp(1563950955, 3), "t" : NumberLong(1), "h" : NumberLong("-1206874032147642463"), "v" : 2, "op" : "i", "ns" : "test.coll", "ui" : UUID("020b51b7-15c2-4525-9c35-cd50f4db100d"), "wall" : ISODate("2019-07-24T06:49:15.903Z"), "o" : { "_id" : ObjectId("5d37ff6b204906ac17e28741"), "x" : 1 } } { "ts" : Timestamp(1563950955, 4), "t" : NumberLong(1), "h" : NumberLong("1059466947856398068"), "v" : 2, "op" : "i", "ns" : "test.coll", "ui" : UUID("020b51b7-15c2-4525-9c35-cd50f4db100d"), "wall" : ISODate("2019-07-24T06:49:15.913Z"), "o" : { "_id" : ObjectId("5d37ff6b204906ac17e28742"), "x" : 2 } }

    上面是 MongoDB oplog 的示例,oplog MongoDB 也是一個集合,但與普通集合不一樣

  • oplog 是一個 capped collection,但超過配置大小后,就會刪除最老插入的數據
  • oplog 集合沒有 id 字段,ts 可以作為 oplog 的唯一標識; oplog 集合的數據本身是按 ts 順序組織的
  • oplog 沒有任何索引字段,通常要找到某條 oplog 要走全表掃描
  • 我們在拉取 oplog 時,第一次從頭開始拉取,然后每次拉取使用完,會記錄最后一條 oplog 的ts字段;如果應用發生重啟,這時需要根據上次拉取的 ts 字段,先找到拉取的起點,然后繼續遍歷。

    oplogHack 優化

    注:以下實現針對 WiredTiger 存儲引擎,需要 MongoDB 3.0+ 版本才能支持

    如果 MongoDB 底層使用的是 WiredTiger 存儲引擎,在存儲 oplog 時,實際上做過優化。MongoDB 會將 ts 字段作為 key,oplog 的內容作為 value,將key-value 存儲到 WiredTiger 引擎里,WiredTiger 默認配置使用 btree 存儲,所以 oplog 的數據在 WT 里實際上也是按 ts 字段順序存儲的,既然是順序存儲,那就有二分查找優化的空間。

    MongoDB find 命令提供了一個選項,專門用于優化 oplog 定位。

    大致意思是,如果你find的集合是oplog,查找條件是針對 ts 字段的?gte、gt、eq?,那么 MongoDB 字段會進行優化,通過二分查找快速定位到起點; 備節點同步拉取oplog時,實際上就帶了這個選項,這樣備節點每次重啟,都能根據上次同步的位點,快速找到同步起點,然后持續保持同步。

    oplogHack 實現

    由于咨詢問題的同學對內部實現感興趣,這里簡單的把重點列出來,要深刻理解,還是得深入擼細節。

    // src/monogo/db/query/get_executor.cpp StatusWith<unique_ptr<PlanExecutor>> getExecutorFind(OperationContext* txn,Collection* collection,const NamespaceString& nss,unique_ptr<CanonicalQuery> canonicalQuery,PlanExecutor::YieldPolicy yieldPolicy) {// 構建 find 執行計劃時,如果發現有 oplogReplay 選項,則走優化路徑if (NULL != collection && canonicalQuery->getQueryRequest().isOplogReplay()) {return getOplogStartHack(txn, collection, std::move(canonicalQuery));}...return getExecutor(txn, collection, std::move(canonicalQuery), PlanExecutor::YIELD_AUTO, options); } StatusWith<unique_ptr<PlanExecutor>> getOplogStartHack(OperationContext* txn,Collection* collection,unique_ptr<CanonicalQuery> cq) {// See if the RecordStore supports the oplogStartHack// 如果底層引擎支持(WT支持,mmapv1不支持),根據查詢的ts,找到 startLocconst BSONElement tsElem = extractOplogTsOptime(tsExpr);if (tsElem.type() == bsonTimestamp) {StatusWith<RecordId> goal = oploghack::keyForOptime(tsElem.timestamp());if (goal.isOK()) {// 最終調用 src/mongo/db/storage/wiredtiger/wiredtiger_record_store.cpp::oplogStartHackstartLoc = collection->getRecordStore()->oplogStartHack(txn, goal.getValue());}}// Build our collection scan...// 構建全表掃描參數時,帶上 startLoc,真正執行是會快速定位到這個點CollectionScanParams params;params.collection = collection;params.start = *startLoc;params.direction = CollectionScanParams::FORWARD;params.tailable = cq->getQueryRequest().isTailable(); }


    原文鏈接
    本文為云棲社區原創內容,未經允許不得轉載。

    總結

    以上是生活随笔為你收集整理的MongoDB 定位 oplog 必须全表扫描吗?的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。