閱讀72 返回首頁    go 小米 go 小米6


MongoDB journal 與 oplog,究竟誰先寫入?

MongoDB journal 與 oplog,誰先寫入?最近經常被人問到,本文主要科普一下 MongoDB 裏 oplog 以及 journal 這兩個概念。

journal

journal 是 MongoDB 存儲引擎層的概念,目前 MongoDB主要支持 mmapv1、wiredtiger、mongorocks 等存儲引擎,都支持配置journal。

MongoDB 所有的數據寫入、讀取最終都是調存儲引擎層的接口來存儲、讀取數據,journal 是存儲引擎存儲數據時的一種輔助機製。

以wiredtiger 為例,如果不配置 journal,寫入 wiredtiger 的數據,並不會立即持久化存儲;而是每分鍾會做一次全量的checkpoint(storage.syncPeriodSecs配置項,默認為1分鍾),將所有的數據持久化。如果中間出現宕機,那麼數據隻能恢複到最近的一次checkpoint,這樣最多可能丟掉1分鍾的數據。

所以建議「一定要開啟journal」,開啟 journal 後,每次寫入會記錄一條操作日誌(通過journal可以重新構造出寫入的數據)。這樣即使出現宕機,啟動時 Wiredtiger 會先將數據恢複到最近的一次checkpoint的點,然後重放後續的 journal 操作日誌來恢複數據。

MongoDB 裏的 journal 行為 主要由2個參數控製,storage.journal.enabled 決定是否開啟journal,storage.journal.commitInternalMs 決定 journal 刷盤的間隔,默認為100ms,用戶也可以通過寫入時指定 writeConcern 為 {j: ture} 來每次寫入時都確保 journal 刷盤。

oplog

oplog 是 MongoDB 主從複製層麵的一個概念,通過 oplog 來實現複製集節點間數據同步,客戶端將數據寫入到 Primary,Primary 寫入數據後會記錄一條 oplog,Secondary 從 Primary(或其他 Secondary )拉取 oplog 並重放,來確保複製集裏每個節點存儲相同的數據。

oplog 在 MongoDB 裏是一個普通的 capped collection,對於存儲引擎來說,oplog隻是一部分普通的數據而已。

MongoDB 的一次寫入

MongoDB 複製集裏寫入一個文檔時,需要修改如下數據

  1. 將文檔數據寫入對應的集合
  2. 更新集合的所有索引信息
  3. 寫入一條oplog用於同步

上麵3個修改操作,需要確保要麼都成功,要麼都失敗,不能出現部分成功的情況,否則

  • 如果數據寫入成功,但索引寫入失敗,那麼會出現某個數據,通過全表掃描能讀取到,但通過索引就無法讀取
  • 如果數據、索引都寫入成功,但 oplog 寫入不成功,那麼寫入操作就不能正常的同步到備節點,出現主備數據不一致的情況

MongoDB 在寫入數據時,會將上述3個操作放到一個 wiredtiger 的事務裏,確保「原子性」。

beginTransaction();
writeDataToColleciton();
writeCollectionIndex();
writeOplog();
commitTransaction();

_2017_03_31_9_11_53

wiredtiger 提交事務時,會將所有修改操作應用,並將上述3個操作寫入到一條 journal 操作日誌裏;後台會周期性的checkpoint,將修改持久化,並移除無用的journal。

從數據布局看,oplog 與 journal 的關係

_2017_03_31_9_54_35

誰先寫入??

  • oplog 與 journal 是 MongoDB 裏不同層次的概念,放在一起比先後本身是不合理的。
  • oplog 在 MongoDB 裏是一個普通的集合,所以 oplog 的寫入與普通集合的寫入並無區別。
  • 一次寫入,會對應數據、索引,oplog的修改,而這3個修改,會對應一條journal操作日誌。

最後更新:2017-04-01 17:13:52

  上一篇:go Blockchain and its Impact on Different Sectors
  下一篇:go StreamingPro 再次支持 Structured Streaming