1. 程式人生 > >MongoDB寫入過程

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的一次資料寫入過程才算完成。