mongoDB研究筆記:journaling保證意外故障下的資料完整性

郭遠威發表於2013-09-08

mongoDB的Journaling日誌功能與常見的log日誌是不一樣的,mongoDB也有log日誌,它只是簡單記錄了資料庫在伺服器上的啟動資訊、慢查詢記錄、資料庫異常資訊、客戶端與資料庫伺服器連線、斷開等資訊。Journaling日誌功能則是mongoDB裡面非常重要的一個功能,它保證了資料庫伺服器在意外斷電、自然災害等情況發生下資料的完整性。儘管mongoDB還提供了其它的複製集等備份措施(後面會分析),但Journaling的功能在生產環境中是不可缺少的,它依靠了較小的CPU和記憶體消耗,帶來的是資料庫的永續性和穩定性。本篇章將分析Journaling涉及到的功能細節問題。Journaling的工作流程?

 幾個重要的儲存檢視

Journaling功能用到了兩個重要的記憶體檢視:private view和shared view。這兩個記憶體檢視都是通過MMAP(記憶體對映)來實現的,其中對private view的對映的記憶體修改不會影響到磁碟上,shared view中資料的變化會影響到磁碟上的檔案,系統會週期性的重新整理shared view中的資料到磁碟。

(1) shared view在mongoDB啟動的過程中,作業系統會將磁碟上的資料檔案對映到記憶體中的shared view,作業系統只是完成對映,並沒有立即載入資料到記憶體,mongoDB會根據需要載入資料到shared view。

(2)private view 記憶體檢視是為讀操作儲存資料的位置,是mongoDB儲存新的寫操作的第一個地方。

(3)磁碟上的Journaling日誌檔案,是實現寫操作持久化儲存的地方。mongoDB例項啟動時會讀這個檔案。

 處理寫操作的流程

     當寫操作發生時,mongoDB首先將資料寫到記憶體中的private view處,然後將寫操作批量複製到journal,journal會將寫操作儲存到磁碟上的檔案上,使其持久化儲存,journal日誌檔案上的每一個條目都描述了寫操作更改了資料檔案上的哪些位元組。

     當上面的步驟完成後,mongoDB接下來會利用journal日誌中的寫操作記錄來更新shared view中的資料,此時記憶體中的資料與磁碟上的資料變得不一致。按照預設值60秒,mongoDB會週期性的要求作業系統將shared view中變化的資料重新整理到磁碟上,使磁碟上的資料與記憶體中的資料保持一致。

當執行完重新整理記憶體中變化的資料到磁碟後,mongoDB會刪除掉journal中這個時間點後面的所有寫操作。

最後,mongoDB會將shared view與private view重新同步,保持一致性。

mongoDB的journaling日誌功能,在2.0版本後是預設啟動的,可以在例項mongod啟動時,通過啟動選項控制;上面提到的步驟中,有一個地方是將寫操作週期性批量寫到journal日誌檔案中,這個週期的大小是通過可選啟動引數journalCommitInterval來控制的,預設值是100ms。

mongoDB經過60s的週期重新整理記憶體中變化的資料到磁碟,這個值通過啟動可選引數syncdelay來控制的。這些預設值一般適用於大多數情況,不要輕易更改。通過上面的分析,資料庫伺服器仍然有100ms的丟失資料的風險,因為journaling日誌的寫到磁碟上的週期是100ms,假如剛好一批寫操還在記憶體中,沒來得及刷到journaling在磁碟上對應的檔案上,伺服器突然故障,這些在記憶體中的寫操作就會丟失。

mongoDB在啟動時,專門初始化一個執行緒不斷迴圈,用於在一定時間週期內來從defer佇列中獲取要持久化的資料並寫入到磁碟的journal(日誌)和mongofile(資料)處,當然因為它不是在使用者新增記錄時就寫到磁碟上,所以按mongodb開發者說,它不會造成效能上的損耗,因為看過程式碼發現,當進行CUD操作時,記錄(Record型別)都被放入到defer佇列中以供延時批量(group commit)提交寫入。 

總之mongoDB利用記憶體對映的技術來完成這些功能,需要參考unix環境程式設計中的記憶體對映MMAP,檔案IO等程式設計知識。

相關文章