MongoDB寫入過程

    MongoDB在寫入前,首先需要與服務器進行連接再發送請求,服務端的處理流程如下:

    Mongod在啓動時會創建一個PortMessageServer對象,其調用setupSockets爲mongod配置的每個地址創建一個socket,並bind地址,然後調用initAndListen監聽所有的地址,調用select等待監聽fd上發生的鏈接時間,調用accept系統接受新的連接請求,併爲每個連接創建一個線程,執行handleIncomingMsg方法。

    handleIncomingMsg會創建一個新的Client對象,並不斷調用recv從連接上讀取請求,並將請求反序列化爲Message對象,並調用MyMessageHandler::process方法處理請求。

    MyMessageHandler::process會調用assembleResponse方法,從Message對象裏獲取請求類型,根據請求類型進行相應的處理。如果是dbInsert,會調用receivedInsert處理,再調用database類的接口定位對應的Collection對象,然後調用insertDocement往集合寫入文檔。

    接下來解釋一下MongoDB的存儲引擎

   

    從MongoDB 3.0之後引入的WiredTiger彌補了MMAP存儲引擎自身的天然缺陷(耗費磁盤空間和內存空間且難以清理,更致命的是庫級別鎖)。

    WiredTiger通過MVCC實現文檔級別的鎖,這樣就允許了多個客戶端請求同時更新一個集合內的不同文檔。

    迴歸主題,上文說到調用insertDocement來寫文檔,那麼存儲引擎的處理過程就是,先寫journal日誌,然後通過多版本併發控制(MVCC)。操作開始之時,WiredTiger 提供了一個時間點快照。快照提供了內存數據的一致性視圖,這樣就能修改該文檔內容。

    都知道NoSQL快,其實上文並沒有體現,關鍵快在,MongoDB修改的是內存的文檔,接着就直接返回了。接下來就有必要了解一下這過程的詳細信息。

   Mongo使用了內存映射技術 - 寫入數據時候只要在內存裏完成就可以返回給應用程序,而保存到硬體的操作則在後臺異步完成。先了解一下Memeory-Mapped Files

  1. 內存映射文件是OS通過mmap在內存中創建一個數據文件,這樣就把文件映射到一個虛擬內存的區域。
  2. 虛擬內存對於進程來說,是一個物理內存的抽象,尋址空間大小爲2^64
  3. 操作系統通過mmap來把進程所需的所有數據映射到這個地址空間(紅線),然後再把當前需要處理的數據映射到物理內存(灰線)
  4. 當進程訪問某個數據時,如果數據不在虛擬內存裏,觸發page fault,然後OS從硬盤裏把數據加載進虛擬內存和物理內存
  5. 如果物理內存滿了,觸發swap-out操作,這時有些數據就需要寫回磁盤,如果是純粹的內存數據,寫回swap分區,如果不是就寫回磁盤。

MongoDB的存儲模型

    MongoDB把文檔寫進內存之後就返回了,那麼接下來的數據的一致性問題、持久化問題,就由上文點到的journal日誌來實現了。默認情況下mongodb每100毫秒往journal文件中flush一次數據,默認每隔60秒,MongoDB請求操作系統將Shared view刷新輸出到磁盤,此外,journal日誌還可以用來做備份容災。

    這樣Mongo的一次數據寫入過程纔算完成。

   

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