MongoDB(引擎)關於存儲引擎 WiredTiger storage engine

 

WiredTiger 在3.2版本成爲mongodb的默認存儲引擎。因此這裏講的就是WiredTiger了。node

Document Level Concurrency算法

WiredTiger提供了document-level concurrency control 的寫操做,這麼說,多個client能夠在同一時間內修改同一collection的不一樣文檔。對於大多數讀寫操做,WiredTiger都會使用最佳的併發控制,在global、database、collection等級別上只使用了意向鎖(intent lock)。若是存儲引擎檢測到兩個操做衝突了,則致使mongodb將其中一個操做從新執行。mongodb

Snapshots and Checkpoints數據庫

MongoDB配置WiredTiger在每60秒或者2GB日誌數據就建立一個checkpoint(快照)。在寫入一個checkpoint時,前一個checkpoint仍然是有效的,因此在此時MongoDB若是崩潰了,仍是能夠回退到最新的有效checkpoint,並依靠日誌來恢復最近的改變。在新的checkpoint成功變成有效的,以前的舊checkpoint pages就會被釋放。併發

Journalapp

MongoDB在沒有新的checkpoint生成以前,會持續地打日誌,使用的是snappy compression library來壓縮日誌,可是也能夠指定其餘的壓縮算法,這可經過storage.wiredTiger.engineConfig.journalConpressor來設置。甚至設置storage.journal.enabled=false來關閉日誌系統,這樣能夠減小花費,可是所作的修改也就很危險。this

MongoDB配置了WiredTiger在內存指定緩衝區中進行記錄,等到達 128 kb 時再寫到磁盤中去。將內存中的記錄寫入磁盤有下面一些條件:spa

  • 每通過100ms。
  • 新的checkpoint出現,或者日誌數據到達2GB。
  • 若是設置了write concern 的j:true選項,存儲引擎馬上寫入log file。

最小的log記錄是128字節,若是等於小於128字節則不使用壓縮。log file的大小規定爲100M,因此存儲引擎大約每100M的日誌數據就建立一個log file,通常會預先建立一些log file(一般是在首次啓動mongod實例以前,此功能能夠關閉)。除非寫操做特別多,不然通常狀況下只會有兩三日誌文件。正常關閉mongod時會清空全部的日誌文件,而非正常關閉則會留下一些文件。操作系統

若是在日誌信息仍在內存緩衝區的時候mongd忽然崩潰(如斷電),這些日誌數據就會丟失。最有可能丟失的就是崩潰前的100ms再加上寫進日誌文件的這一時間段。serverStatus
命令中有log的統計信息。日誌

若是頻繁寫日誌文件會致使效率的降低,這時能夠將journal目錄轉移到其餘文件系統中,就不會影響到數據庫正常的讀寫操做效率。但這會帶來的一個問題是,對數據庫使用snapshot時不可以對這兩個部分單獨進行操做,而是須要使用fsyncLock()將數據庫鎖起來,等snapshot操做都完成以後再使用fsyncUnlock()解鎖。

Compression

MongoDB提供collection壓縮和index壓縮。默認是使用block compression來壓縮collection,和使用prefix compression來壓縮index。
對於collection,能夠更改指定壓縮算法或者禁用壓縮,使用storage.wiredTiger.collectionConfig.blockCompressor設置便可。
對於index,可使用storage.wiredTiger.indexConfig.prefixCompression來關閉prefix壓縮。
甚至,針對每一個collection和index的壓縮,可使用具體的壓縮算法,參考create-collection-storage-engine-optionsdb.collection.createIndex()。不過,默認的壓縮算法在大多數平均狀況下都有出色的表現,很好平衡了效率和執行需求。

Cache

MongoDB使用了雙Cache,一個是WiredTiger Cache,一個是文件系統Cache。默認狀況下,從3.2起WiredTiger將使用60%的RAM減去1GB或者使用1GB,取其中的大者。在3.0中要麼使用1GB,要麼50%的物理內存,取其中的大者。能夠參考storage.wiredTiger.engineConfig.cacheSizeGB
--wiredTigerCacheSizeGB進行配置Cache大小,可是要避免超過默認的大小,值得注意的是,storage.wiredTiger.engineConfig.cacheSizeGB僅僅限制了WiredTiger Cache的大小,這只是mongod的一部分,而不是mongod所使用內存的上限。MongoDB假設了這隻有一個instance在一個node上而已,若是有多個的話,更加須要調整一下Cache大小。

本引擎會自主決定哪些數據保存在內存中,哪些數據會刷新到磁盤中。並且,兩種引擎不能混淆使用,即用Wired Tiger建立的數據庫不能用MMAPv1去打開,這是兩種不一樣的文件存儲方式以及管理方式的。

關於MMAPv1 storage engine

每一個文檔中的全部field都位於同一塊連續的內存中,而storage engine在爲文檔申請內存塊的時候都是會留出一部份內存供後來填充用的,即爲每一個文檔申請的實際內存大小都會大於其真實大小(通常是以2的指數增加)。當填充的多餘部份內存用光了以後,就會引發從新爲該文檔申請新內存的操做。

Document Level Lock

本引擎也提供了鎖的機制,對於document級別的寫操做保證了不會衝突,而是進行有序的執行。

MongoDB 系統的限制與門檻

  • BSON文檔
    最大BSON文檔的大小是16MB,若是超過這個限制,能夠嘗試使用GridFS API來存儲大文件。
  • 嵌套深度
    MongoDB目前支持的內嵌文檔的嵌套深度是不超過100層。
  • Namespace 長度
    支持的最大的集合namespace爲120 Bytes,其中包括了數據庫名稱,還有dot等等,即<database>.<collection>
  • Namespace 的數量
    在3.0以前使用的默認存儲引擎就會有一些限制,好比Namespace的數量受限制於namespace文件的大小,如今的默認存儲引擎WiredTiget就沒有這些限制了。
  • Namespace 文件的大小
    以前MMAPv1默認的namespace文件的大小限制爲16MB,可是能夠經過nsSize來配置它,只要不超過2047字節。但WiredTiger如今沒有這個限制。
  • 固定集合Capped Collection。若是是經過max參數來建立的固定集合,那麼集合大小不能超過232。而在建立固定集合的時候沒有指定集合大小,那麼集合中能夠包含任意多個文檔。
  • MMAPv1存儲引擎限制了每一個數據庫不可以超過16000個數據文件,即不超過32TB,可經過storage.mmapv1.smallFiles來設置爲8TB。
  • MMAPv1不可以處理數據大小超過操做系統的虛存空間大小。而WiredTiger沒有此限制。
  • MMAPv1限制了數據庫中的文檔數量,與索引數量和namespace文件大小相關。WiredTiger沒有此限制。
  • 針對具體狀況,可使用no padding模式的申請內存方式,這樣每次申請的內存大小就剛恰好了。

GridFS 大文檔存儲

若是存儲的文檔超過了16MB,那麼就須要選擇這種方式來存儲了。將大文檔分割成小部分或chunk,而後分別做爲小文檔存儲起來,分別存儲於兩個集合collection中,其中一個集合存儲的是文件chunk,另外一個存儲的是元數據(這裏有詳細介紹 GridFS Collections)。默認的chunk大小爲255kB,即除了最後一塊,其餘都是255kB(自從v 2.4.10改成255kB的)。
在須要查詢大文件的時候,引擎會重組全部的chunk。能夠針對文件中的某個範圍進行查詢,好比跳過視頻的片頭。這種存儲方式也支持16MB如下的文檔存儲的,當常常須要查詢文件中的某個範圍的時候就能派上用場了。

通常狀況下,GridFS使用兩個分別名爲fs.filesfs.chunks的文件來保存全部的大文件信息。一對文件稱之爲「桶」,能夠建立多對,也能夠選擇其餘名稱。chunks中的每一個文檔都是一個chunk,就像下面這樣:

{ 
  "_id" : <ObjectId>, 
  "files_id" : <ObjectId>,
  "n" : <num>,   //sequence of this chunk
  "data" : <binary>
}

files中的每一個文檔表明着GridFS中的一個大文件。除了部分是可選的,文檔格式大體以下:

{ 
  "_id" : <ObjectId>, 
  "length" : <num>, 
  "chunkSize" : <num>, 
  "uploadDate" : <timestamp>, 
  "md5" : <hash>, 
  "filename" : <string>, 
  "contentType" : <string>, 
  "aliases" : <string array>, 
  "metadata" : <dataObject>
}

那效率如何呢?GridFS對每一個chunks和files集合使用了index,驅動通常會自動建立這些索引,提高速度就只能依靠這些索引了,也能夠自定義一些新索引。

相關文章
相關標籤/搜索