mongodb使用的存儲引擎有:1、WiredTiger存儲引擎是mongodb3.2的默認存儲引擎;2、MMAPv1是mongodb基于內存映射最初的存儲引擎;3、In-Memory是一種內存存儲引擎,它是非持久性的,不會持久化數據。
一、mongodb存儲引擎種類
mongodb主要有3種存儲引擎,分別是:
(1) WiredTiger
(2) MMAPv1
(3) In-Memory
下面分別介紹這三種存儲引擎。
二、WiredTiger
MongoDB 3.0版本開始啟用,64位版本。
MongoDB 3.2 成為默認存儲引擎
(1) 文檔級別的并發
WiredTiger 對寫操作執行文檔級別的并發控制,也就是說,在同一時間,可以修改一個集合中的不同文檔。
針對大多數的讀寫操作,WiredTiger采取樂觀的并發控制機制。WiredTiger 在全局、數據庫和集合級別身上僅使用意向鎖。當存儲引擎檢測到兩個操作產生沖突時,其中一個操作會引發一個寫沖突,促使mongodb顯式的的重新執行該操作。
一些全局的操作,典型的有涉及多個庫的短暫操作,需要實例鎖;
一些像刪除集合的操作,還需要排他鎖。
(2) 快照和檢查點
WiredTiger 使用多版本的并發控制(MVCC)。
一個操作開始時,WiredTiger 會為事務提供一個實時的數據快照,快照呈現內存中數據的一致性視圖。
將數據寫入磁盤時,WiredTiger 以一致性的方式將快照中的所有數據寫入磁盤。檢查點確保數據文件中所有的數據是一致的,并且包含最后一個檢查點。檢查點可以作為回復數據的點。mongodb配置WiredTiger 來創建檢查點(即將快照數據寫入磁盤),創建的時機是:每60秒或者當日志文件達到2G。
在寫一個新檢查點的過程中,上一個檢查點仍然是有效的,如果寫的過程中出現宕機或者其他異常,一旦重啟成功,mongodb會從上一個有效的檢查點恢復數據。
當WiredTiger的元數據表關聯到新的檢查點時,該新的檢查點才是可訪問和持久的,此時,會釋放老檢查點的頁。
(3) 日志文件系統Journal
默認提交時間間隔為100毫秒。
WiredTiger使用預寫事務日志與檢查點結合的方式來確保數據持久化。即開啟Journal功能,Journal會記錄在兩個檢查點之間的所有修改,當mongodb突然退出并重啟之后,WiredTiger會根據Journal中的記錄恢復最后一個檢查點之后發生的數據修改。
Journal用snappy庫壓縮。用storage.wiredTiger.engineConfig.journalCompressor指定其他的壓縮算法或者不采用壓縮策略。WiredTiger 最小的日志記錄大小是128字節,如果記錄為128字節或者更小,則不會壓縮該條記錄。
將storage.journal.enabled設置為False,則不會啟動Journaling。
對單實例而言,如果禁用journal意味著我們會丟失mongodb異常終止后上一個有效檢查點之后的所有數據。對于復制集(主從的mongodb集群)中的一些成員來說,復制過程可能提供充分的持久性保證。
(4) 壓縮
使用WiredTiger存儲引擎,mongodb支持壓縮所有集合和索引。壓縮以使用額外的CPU為代價來降低存儲消耗。WiredTiger 對集合采用塊壓縮(使用snappy壓縮庫或者zlib),對索引采用前綴壓縮。可以通過配置來更改壓縮方式,換用其他壓縮算法或者不進行壓縮。再建立一個集合或者一個索引的時候,可以為其制定壓縮方式。對于大多數的工作負載,默認的壓縮設置會平衡存儲效率和處理需求。
(5) 內存使用
使用WiredTiger存儲引擎,MongoDB 既會使用WiredTiger的內部緩存,也會使用文件系統的緩存.
從MongoDB3.4開始,WiredTiger 內部緩存會使用下面兩個數中的較大者:
a. RAM的50% 減去1 GB
b. 256MB
對于文件系統緩存,MongoDB會自動使用除WiredTiger內部緩存以及其他進程占用內存的所有空閑內存。文件系統中的緩存會被壓縮。
想要調整WiredTiger的內部緩存, 可以參考storage.wiredTiger.engineConfig.cacheSizeGB和wiredTigerCacheSizeGB.
避免增加WiredTiger內部緩存的大小超過其默認值。
三、MMAPv1
MMAPv1是MongoDB基于內存映射的最初的存儲引擎,它在大量的讀寫和就地更新的任務上有很好的表現。從3.2版本開始,MMAPv1 不在是默認的存儲引擎。
注意:big-endian架構不支持MMAPv1存儲引擎,如果在大端機器上采用該存儲引擎,會報錯。Endian表示數據在存儲器中的存放順序,采用大端方式 進行數據存放符合人類的正常思維,而采用小端方式進行數據存放利于計算機處理。大端指低地址存放最高有效字節,小端是指低地址存放最低有效字節。
例如:我們要存儲一個16進制的數0x31323334;
小端機器的存儲方式為:
低地址 –> 高地址
34 33 32 31
大端機器的存儲方式為:
低地址 –> 高地址
31 32 33 34
(1) Journal
為了確保所有的數據都被持久化到磁盤,MongoDB默認將所有修改都保存到磁盤的日志文件中,MongoDB寫日志文件要比寫數據文件頻繁。
storage.syncPeriodSecs:設置數據文件存儲時間間隔,默認60秒。不要在生產環境設置該參數,在幾乎所有場景,你都應該用該默認的參數,如果將該參數設置為0,MongoDB 將不會同步內存映射文件到磁盤。
storage.journal.commitIntervalMs:默認值為100毫秒或30毫秒,取值范圍是0~500毫秒,取值越低,數據持久性越高,但是會犧牲磁盤性能。
默認日志存儲時間間隔為100毫秒。但是如果日志文件被存儲在于數據文件不同的區塊設備上,例如physical volume, RAID device, or LVM volume,默認日志提交間隔會變為30毫秒,此外, when a write operation with j:true is pending, 提交的時間間隔將要變成設置值的三分之一。
在許多情況下,MongoDB 和操作系統更新數據到磁盤要比設置的時間間隔頻繁的多,所以,以上的設置值只是理論上的最大值。
當mongod實例異常退出時,MongoDB 可以根據這些數據文件恢復數據庫。
(2) 記錄存儲特性
所有記錄都是連續的存儲在磁盤上,當一條記錄被更新并且超出原來分配的記錄大小,則需要重新分配一個記錄,之后將文檔移動到新記錄中,并且更新與文檔相關的所有索引。這顯然比原地更新記錄要花費更多的時間,同時還會導致存儲碎片。
從3.0版本開始,分配策略有所改變。
(3) 記錄分配策略
從3.0版本開始,MongoDB使用Power of 2 Sized Allocations策略,將一個文檔存儲到一條記錄中,同時記錄中還有額外的空間,這些額外的空間允許更新操作帶來的文檔大小的增長,使得重新分配內存的可能新降到最低。
不同的分配策略支持不同種類的操作:
the power of 2 allocations:對insert/update/delete操作更加有效; 采用該策略之后,所有記錄的大小均為2的n次冪字節。對于大于2MB的文檔,分配將要向上取整到2MB的倍數。該策略有以下兩個關鍵特性:
能重新使用釋放的記錄來減少碎片。
能減少文檔移動,但是不能完全消除重新分配的情況。
exact fit allocations(No Padding Allocation Strategy):對沒有更新和刪除操作的集合更理想。
對于那些沒有改變文檔大小操作或者只有插入操作的集合,我們可以將the power of 2 allocations設置為無效。在3.0版本以前,MongoDB 通過動態計算填充大小來作為文檔大小的因素。
(4) 內存使用
采用MMAPv1存儲引擎,MongoDB自動使用機器所有空閑的內存作為它的緩存,系統資源監控顯示,MongoDB用了許多內存,但是它的使用是動態的,當其他進程需要使用內存時,MongoDB會放棄部分緩存所占用的內存給其他進程。
從技術上來說,操作系統的虛擬內存子系統管理著MongoDB內存,這意味著MongoDB會盡可能多的使用空閑內存,當需要的是有也會切換到磁盤,部署足夠的內存來適應工作數據集將會獲得做好的性能。
三、In-Memory(內存存儲引擎)
(1) 并發性
內存存儲引擎使用文檔級別的并發控制,可以在同一時刻對不同文檔進行更新操作。
(2) 內存使用
內存存儲引擎要求它的所有數據必須符合在命令行參數(–inMemorySizeGB)或者在YAML配置文件中設置的內存大小。
默認情況下,內存存儲引擎使用物理RAM的50%減去1 GB的內存。
如果一個寫操作超出指定的內存大小,mongodb將會報錯,錯誤信息如下:
“WT_CACHE_FULL: operation would overflow cache”
(3) 持久化
內存存儲引擎是非持久性的,不會持久化數據。非持久化的數據包括應用程序數據,系統數據,例如用戶、權限、索引、副本設置配置、分片集群配置等。數據庫正常或者異常關閉的情況下,數據均不可恢復。
在采用內存存儲引擎,或者其他存儲引擎但是關閉了Journal功能是,必須將writeConcernMajorityJournalDefault參數設置為False。
(4) 部署結構
除了作為單實例運行,采用內存存儲引擎的mongod實例也可以作為副本集或者分片集群的一部分。
作為副本集的一部分
例如,一個有三個成員的副本集,其結構可以為:
兩個mongod實例運行在In-Memory存儲引擎上
另外一個mongod實例運行在WiredTiger存儲引擎上,并將該實例配置為隱藏成員。
在該配置結構下,只有采用IN-memory的數據庫實例會被選舉為最主要者,客戶端只會連接到該實例上。即使兩個使用In-memory的數據庫實例均死機或者重啟,他們都會從運行在WiredTiger的實例上同步數據。隱藏的數據庫實例會將用戶數據、索引和其他復制配置信息都持久化到磁盤上。
作為分片集群的一部分
例如,一個有三個成員的分片集群,其結構可以為:
兩個mongod實例運行在In-Memory存儲引擎上
另外一個mongod實例運行在WiredTiger存儲引擎上,并將該實例配置為隱藏成員。
為分片加inmem標簽。如果該分片的名字為”shardC”,則連接mongos ,然后運行sh.addShardTag(“shardC”, “inmem”),對于其他的分片,分別添加一個persisted 標簽,
sh.addShardTag(“shardA”, “persisted”)
sh.addShardTag(“shardB”, “persisted”)
對于每個應該駐留在內存中的分片集合,分配給整塊范圍的inmem標簽。
sh.addTagRange(“test.analytics”, { shardKey: MinKey }, { shardKey: MaxKey }, “inmem”)
對于每個應該駐留在持久化中的分片集合,分配給整塊范圍的persisted標簽。:
sh.addTagRange(“salesdb.orders”, { shardKey: MinKey }, { shardKey: MaxKey }, “persisted”)
對于內存中的分片,創建一個數據庫或者移動一個數據庫。