您好,登錄后才能下訂單哦!
Mongodb中oplog的原理是什么,針對這個問題,這篇文章詳細介紹了相對應的分析和解答,希望可以幫助更多想解決這個問題的小伙伴找到更簡單易行的方法。
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 工具。
關于Mongodb中oplog的原理是什么問題的解答就分享到這里了,希望以上內容可以對大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關注億速云行業資訊頻道了解更多相關知識。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。