在MongoDB中,文檔是對數據的抽象,它被使用在Client端和Server端的交互中。全部的Client端(各類語言的Driver)都會使用這種抽象,它的表現形式就是咱們常說的BSON(Binary JSON )。mongodb
BSON是一個輕量級的二進制數據格式。MongoDB可以使用BSON,並將BSON做爲數據的存儲存放在磁盤中。數據庫
當Client端要將寫入文檔,使用查詢等等操做時,須要將文檔編碼爲BSON格式,而後再發送給Server端。一樣,Server端的返回結果也是編碼爲BSON格式再放回給Client端的。服務器
使用BSON格式出於如下3種目的:性能
BSON是爲效率而設計的,它只須要使用不多的空間。即便在最壞的狀況下,BSON格式也比JSON格式再最好的狀況下存儲效率高。編碼
在某些狀況下,BSON會犧牲額外的空間讓數據的傳輸更加方便。好比,字符串的傳輸的前綴會標識字符串的長度,而不是在字符串的末尾打上結束的標記。這樣的傳輸形式有利於MongoDB修改傳輸的數據。spa
最後,BSON格式的編碼和解碼都是很是快速的。它使用了C風格的數據表現形式,這樣在各類語言中均可以高效地使用。 操作系統
寫入協議設計
Client端訪問Server端使用了輕量級的TCP/IP寫入協議。這種協議在MongoDB Wiki中有詳細介紹,它實際上是在BSON數據上面作了一層簡單的包裝。好比說,寫入數據的命令中包含了1個20字節的消息頭(由消息的長度和寫入命令標識組成),須要寫入的Collection名稱和須要寫入的數據。指針
數據文件日誌
在MongoDB的數據文件夾中(默認路徑是/data/db)由構成數據庫的全部文件。每個數據庫都包含一個.ns文件和一些數據文件,其中數據文件會隨着數據量的增長而變多。因此若是有一個數據庫名字叫作foo,那麼構成foo這個數據庫的文件就會由foo.ns,foo.0,foo.1,foo.2等等組成。
數據文件每新增一次,大小都會是上一個數據文件的2倍,每一個數據文件最大2G。這樣的設計有利於防止數據量較小的數據庫浪費過多的空間,同時又能保證數據量較大的數據庫有相應的空間使用。
MongoDB會使用預分配方式來保證寫入性能的穩定(這種方式可使用–noprealloc關閉),預分配的方式能夠減小碎片。預分配在後臺進行,而且每一個預分配的文件都用0進行填充。這會讓MongoDB始終保持額外的空間和空餘的數據文件,從而避免了數據增加過快而帶來的分配磁盤空間引發的阻塞。
每個數據庫都由多個名字空間組成,每個名字空間存儲了相應類型的數據。數據庫中的每個Collection都有各自對應的名字空間,索引文件一樣也有名字空間。全部名字空間的元數據都存儲在.ns文件中。
名字空間中的數據在磁盤中分爲多個區間,這個叫作盤區。在下圖中,foo這個數據庫包含3個數據文件,第三個數據文件屬於空的預分配文件。頭兩個數據文件被分爲了相應的盤區對應不一樣的名字空間。
每個名字空間能夠包含多個不一樣的盤區,這些盤區並非連續的。與數據文件的增加相同,每個名字空間對應的盤區大小的也是隨着分配的次數不斷增加的。這樣作的目的是爲了平衡名字空間浪費的空間與保持某一個名字空間中數據的連續性。還有一個須要注意的名字空間:$freelist,這個名字空間用於記錄再也不使用的盤區(被刪除的Collection或索引)。每當名字空間須要分配新的盤區的時候,都會先查看$freelist是否有大小合適的盤區可使用。
MongoDB目前支持的存儲引擎爲內存映射引擎。當MongoDB啓動的時候,會將全部的數據文件映射到內存中,而後操做系統會託管全部的磁盤操做。(這裏的意思就是,MongoDB中的數據能夠經過Java中的new操做設置一個對象,進而將對象映射到內存中,內存根據指針等實現對磁盤的操做)這種存儲引擎有如下幾種特色:
* MongoDB中關於內存管理的代碼很是精簡,畢竟相關的工做已經有操做系統進行託管。
* MongoDB服務器使用的虛擬內存將很是巨大,並將超過整個數據文件的大小。不用擔憂,操做系統會去處理這一切。
* MongoDB沒法控制數據寫入磁盤的順序,這樣將致使MongoDB沒法實現writeahead日誌的特性。因此,若是MongoDB但願提供一種durability的特性,須要實現另一種存儲引擎。
* 32位系統的MongoDB服務器每個Mongod實例只能使用2G的數據文件。這是因爲地址指針只能支持32位。