MongoDB的Journal

MongoDB採用提前寫日誌到磁盤日誌文件的方式來實現發生故障時的數據持久化。
Journal是一個連續的、二進制的事務日誌,在突然停機時,我們用它來恢復數據庫到一個有效的狀態。
下面分別介紹Journaling在三種不同存儲引擎下的作用。

一、WiredTiger
WiredTiger使用檢查點來爲磁盤上的數據提供一個一致性的試圖,允許MongoDB從上一個檢查點恢復數據。然而,如果MongoDB在兩個檢查點之間意外退出,則會丟失兩個檢查點之間的數據。此時我們需要用Journaling來恢復最後一個檢查點之後產生的信息。
1、使用journaling,恢復數據的步驟如下:

(1) 在數據文件中查找最後一個檢查點的標識;
(2) 在journal文件中搜索匹配最後一個檢查點標識的記錄;
(3) 應用journal文件中從最後一個檢查點之後的所有操作。

2、日誌記錄的過程(Journaling Process)
WiredTiger 爲每一個客戶端創建一個journal記錄來初始化寫操作。例如,更新集合中的一個文檔會造成索引的修改,WiredTiger 會創建一條單獨journal,該條journal中包含更新操作和與它關聯的索引的修改信息。
MongoDB配置WiredTiger使用內存緩衝來存儲journal記錄。使用線程協調來分配和拷貝到緩衝的部分。所有大於128KB的journal記錄會被緩衝。
WiredTiger 同步*緩衝的journal記錄磁盤*根據以下的時間間隔或者條件:

(1) 在3.2版本中,每50毫秒同步一次
(2) MongoDB設置WiredTiger存儲引擎創建檢查點的時機有兩個:一個是在每60秒的時候,另一個是journal文件中已經寫入了2GB的數據。二者中哪一個先發生都會開始創建檢查點。
(3) 如果寫操作包含一個寫關心j: true,那麼WiredTiger會強制一次journal 文件同步。
(4) 因爲MongoDB有100MB journal文件的限制,WiredTiger 會創建一個新的journal文件近似100MB數據,當創建了一個新的journal文件之後,WiredTiger會同步之前的journal文件。

注意:當在寫操作之間發生突然停機的話,保存在WiredTiger緩存中的更新會丟失。

3、日誌文件(Journal Files)
開啓journaling的情況下,MongoDB會在dbpath下創建一個叫做journal 的子目錄,WiredTiger的journal文件的名字格式爲WiredTigerLog.,其中是一個用0填充的數字,從0000000001開始。
journal文件中包含對應每一次寫操作的一條記錄,每條記錄都有唯一的標識符。WiredTiger 最小的日誌記錄大小是128字節,如果記錄小於128字節,則不會對其壓縮。
WiredTiger 會自動移除老的journal文件,並且僅維護從最後一個檢查點恢復數據時所需的journal文件。

二、MMAPv1
使用MMAPv1存儲引擎,當寫操作發生時,MongoDB會更新內存中的視圖。在journaling開啓時,MongoDB首先將內存中的改變寫入到磁盤上的journal文件中。如果在將數據提交到數據文件之前發生發生終止或錯誤,MongoDB會使用journal文件將寫操作應用到數據文件中,以此來維護一個一致的狀態。
1、日誌記錄的過程(Journaling Process)
使用journaling,MongoDB的存儲層有兩個關於數據集的內部視圖,分別是用於寫入journal文件私有視圖和用於寫入數據文件共享視圖

(1) MongoDB首先將寫操作應用於私有視圖
(2) 然後,MongoDB以大約100毫秒的時間間隔將私有視圖中的更改應用到日誌目錄中的磁盤journal文件中。MongoDB成批地將寫操作記錄到磁盤上的journal文件的操作叫做組提交。這樣做的目的是爲了最小化對journaling的性能影響,因爲這些提交必須在提交期間阻塞所有的寫入器。寫入journal文件具有原子性。
(3) 一經journal提交,MongoDB 會將journal中的所有改變應用到共享視圖中去。
(4) 最後,MongoDB將共享視圖中的改變應用到數據文件中,更準確的說是,每隔60秒,MongoDB 會讓操作系統刷新共享視圖中的數據到數據文件。操作系統有可能會以比60秒更高的頻率去刷新共享視圖中的數據到數據文件,尤其是當系統內存比較小的時候。
MongoDB共享視圖與磁盤上數據文件的交互方式與在不開啓journaling時MongoDB的工作方式類似。不開啓journaling的時候,MongoDB讓操作系統每隔60秒將內存中數據的變化刷新到到磁盤的數據文件中。

2、日誌文件(Journal Files)
開啓journaling的情況下,MongoDB會在dbpath下創建一個叫做journal 的子目錄,journal 目錄下包含一些命名格式爲j._的journal文件,其中從整數0開始,還包含一個“last sequence number” 文件lsn。
Journal 文件包含提前寫日誌;每一個journal條目描述寫操作在數據文件中改變的字節數。Journal 文件是隻追加文件。每當一個journal文件達到1GB,MongoDB 都會創建一個新的journal文件。如果啓動數據庫實例mongod的時候使用storage.smallFiles參數,則限制每一個journal文件的大小爲128 megabytes(百萬字節,近似於MB)
lsn文件中保存着最後一次刷新數據到數據文件的時間。
一旦MongoDB 將某個特定journal文件中的寫操作寫入數據文件後,MongoDB可以將它用於一個新的journal文件。
除非你每秒寫很多數據,否則journal目錄下將僅有兩到三個journal 文件。
乾淨的關機會移除journal目錄下的所有文件,髒關機會將journal文件留在journal目錄下。這些文件會被用在重啓時自動將數據庫恢復數據到一個一致的狀態。

3、日誌目錄(Journal Directory)
爲了加快當前journal文件的頻繁連續寫入,你可以確保journal目錄與數據庫數據文件不在一個文件系統下。
注意:如果你將journal與數據文件放在不同的文件系統下,您不能僅使用文件系統快照來捕獲dbPath目錄的有效備份。在這種情況下,使用fsyncLock()以確保在快照之前數據庫文件是一致的,使用fsyncUnlock() 一旦快照完成。
4、預先分配延遲(Preallocation Lag)
MongoDB 也許會預先分配journal文件如果mongod認爲這樣做比需要的時候再分配更加有效。
根據你的文件系統,你可能會在第一次啓動一個帶有journaling 的mongod實例時經歷一個預先分配的延遲。預分配的時間有可能會持續幾分鐘,在此期間,我們將連接不到數據庫,這是一次性的預分配,不會在將來的調用中發生。
避免預分配延遲的方法
你可以通過拷貝其他mongod實例的預分配文件來預分配該實例下的journal文件。預分配文件不包含數據。以後把它們移走是安全的。但是如果你用journaling重啓數據庫實例,數據庫實例會再一次創建它們。

三、In-Memory
從MongoDB企業版本3.2.6開始,內存存儲引擎成爲通用版本的一部分。由於它的數據存儲在內存中,所以沒有單獨的journal,帶有寫關心j的寫操作會被立即確認。如果副本集中的任何一個成員沒有開啓journaling功能,那必須設置writeConcernMajorityJournalDefault爲false。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章