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
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-options
和db.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去打開,這是兩種不一樣的文件存儲方式以及管理方式的。
每一個文檔中的全部field都位於同一塊連續的內存中,而storage engine在爲文檔申請內存塊的時候都是會留出一部份內存供後來填充用的,即爲每一個文檔申請的實際內存大小都會大於其真實大小(通常是以2的指數增加)。當填充的多餘部份內存用光了以後,就會引發從新爲該文檔申請新內存的操做。
Document Level Lock
本引擎也提供了鎖的機制,對於document級別的寫操做保證了不會衝突,而是進行有序的執行。
<database>.<collection>
。storage.mmapv1.smallFiles
來設置爲8TB。GridFS 大文檔存儲
若是存儲的文檔超過了16MB,那麼就須要選擇這種方式來存儲了。將大文檔分割成小部分或chunk,而後分別做爲小文檔存儲起來,分別存儲於兩個集合collection中,其中一個集合存儲的是文件chunk,另外一個存儲的是元數據(這裏有詳細介紹 GridFS Collections)。默認的chunk大小爲255kB,即除了最後一塊,其餘都是255kB(自從v 2.4.10改成255kB的)。
在須要查詢大文件的時候,引擎會重組全部的chunk。能夠針對文件中的某個範圍進行查詢,好比跳過視頻的片頭。這種存儲方式也支持16MB如下的文檔存儲的,當常常須要查詢文件中的某個範圍的時候就能派上用場了。
通常狀況下,GridFS使用兩個分別名爲fs.files
和fs.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,驅動通常會自動建立這些索引,提高速度就只能依靠這些索引了,也能夠自定義一些新索引。