<a href="#_Toc447290164">9. 存儲... 1</a>
<a href="#_Toc447290165">9.1 存儲引擎... 1</a>
<a href="#_Toc447290166">9.1.1 WiredTiger存儲引擎... 1</a>
<a href="#_Toc447290167">9.1.1.1 文檔級别并發... 1</a>
<a href="#_Toc447290168">9.1.1.2 快照和檢查點... 2</a>
<a href="#_Toc447290169">9.1.1.3 Journaling. 2</a>
<a href="#_Toc447290170">9.1.1.4 壓縮... 2</a>
<a href="#_Toc447290171">9.1.1.5 記憶體使用... 3</a>
<a href="#_Toc447290172">9.1.2 MMAPv1存儲引擎... 4</a>
<a href="#_Toc447290173">9.1.3 In-Memory存儲引擎... 4</a>
<a href="#_Toc447290174">9.2 Journaling. 4</a>
<a href="#_Toc447290175">9.2.1 Journaling和WiredTiger引擎... 4</a>
<a href="#_Toc447290176">9.2.2 journal和MMAPv1引擎... 5</a>
<a href="#_Toc447290177">9.2.3 Journal和in-memory存儲引擎... 6</a>
存儲引擎是資料庫的一個元件用于管理資料存儲。Mongodb支援多存儲引擎,不同的存儲引擎對于指定負荷可能會有更好的性能。
WiredTiger在Mongodb 3.2之後作為預設的存儲引擎,能夠很好的适應很多負荷。WiredTiger提供文檔級别的并發模型,檢查點,壓縮,和其他特性。
MMAPv1是Mongodb老的存儲引擎在mongodb 3.2之前是預設的存儲引擎。
In-Memory Storage Engine在Mongodb 企業版可用。和其他存儲引擎不同資料是存放在記憶體減少資料延遲。
從3.0開始已經在64位系統上可用。
在3.2版本中WiredTiger存儲引擎為預設存儲引擎。如果沒有指定--storageEngine或者storage.engine會自動決定存儲引擎的使用并且存放在storage.dbPath下。
WiredTiger使用文檔級别并發控制寫入操作。這樣多個用戶端可以同時對不同的文檔進行修改。對于很多讀寫操作WiredTiger使用最優的并發控制。WiredTiger在全局,資料庫,collection上使用意向鎖。當存儲引擎發現2個沖突操作,一個操作會出現寫入重提,需要顯示的重試這個操作。
一些全局操作,通常執行時間短的涉及到多個資料庫的,還是會使用全局鎖。對于drop collection還是會有資料庫x鎖。
WiredTiger使用多版本并發控制(MVCC),在操作之前,WiredTiger提供一個資料快照。快照表示記憶體資料庫的視窗。
當寫入磁盤,WiredTiger寫入所有的快照中的資料到磁盤。新的固化資料被當做資料檔案的checkpoint。
MongoDB在每60秒或者2GB journal資料建立checkpoint。
當在建立新的檢查點,老的檢查點還是可用。如果MongDB在寫入checkpoint的時候發生錯誤或者中斷,MongoDB可以使用最後一次有效的checkpoint。
當WiredTiger中繼資料表自動更新引用新的檢查點,新的檢查點變成可用,并且持久。一旦新的checkpoint可用,老的checkpoint就被釋放。
如果沒有開啟journaling,mongodb會從最後一次checkpoint恢複,checkpoint之後的恢複需要用到journaling。
WiredTiger使用日志先行配合checkpoint來保證資料持久性。WiredTiger journal記錄了checkpoint之間的資料修改。如果MongoDB在2次checkpoint之間退出,mongodb會使用journal來重播最後一次checkpoint之後所有的修改。
WiredTiger使用snappy壓縮journal。可以指定其他的壓縮方法,或者不壓縮,可以使用storage.wiredTiger.engineConfig.journalCompressor來設定。
Note:WiredTiger最小的日志記錄是128 bytes,如果小于128 bytes,那麼就不會壓縮記錄
也可以直接關閉journal減少對journal的維護,storage.journal.enabled=false。如果是單執行個體,不使用journal就意味着會丢失修改的資料,特别是mongodb在checkpoint之間不可預見的退出。對于複制集,複制程序可以滿足持久性要求。
使用WiredTiger,MongoDB支援對所有collection和index 進行壓縮。壓縮可以減少存儲的使用但是會花費一點cpu。
預設,WiredTiger使用塊壓縮,使用snappy壓縮方式壓縮所有collection,對所有索引使用字首壓縮。
對于collection,塊壓縮也可以使用zlib。
設定storage.wiredTiger.collectionConfig. blockCompressor。
對于index,取消字首壓縮,storage.wiredTiger.indexConfig.prefixCompression
壓縮設定可以在每個collection或者索引上在建立時設定。對于很多負荷預設壓縮設定平衡了存儲效率和處理要求。
使用WiredTiger,MongoDB利用了WiredTiger的cache和檔案系統的cache。在3.2之後,WiredTiger cache預設為一下2個大的一個:
1.60%的記憶體減去1GB
2.1GB
對于大于10GB的記憶體,新的預設設定會比3.0占用更多記憶體。對于檔案系統緩存,MongoDB自動使用空閑的記憶體。資料在檔案系統cache是被壓縮的。
可以通過配置storage.wiredTiger.engineConfig.cacheSizeGB來調整WiredTiger記憶體大小。
單機修改存儲引擎到WiredTiger
考慮:修改存儲引擎使用mongodump和mongorestore工具來導入導出資料。保證這些工具已經安裝了。另外保證有足夠的空間用于導入導出。為了可以使用WiredTiger必須使用3.0以上版本的MongoDB。
過程
1.啟動mongod,如果已經啟動跳過
2.使用mongodump導出
3.建立一個資料庫目錄用于新版本的mongodb運作
4.啟動帶WiredTiger的MongoDB
5.使用mongorestore來恢複資料。
修改複制集到WiredTiger
考慮:對于複制集有成員使用不同的存儲引擎。那麼你可以以滾動的方式逐個修改到WiredTiger。在全部修改到WiredTiger之前,最好使用混合的存儲引擎方式運作一段時間。
1.關閉該secondary成員,db.shutdownServer()
2.準備一個有WiredTiger的MongoDB建立一個資料庫目錄
3.啟動帶WiredTiger的MongoDB,因為沒有資料,mongod會執行初始化同步,初始化時間取決于資料庫的大小和網絡連接配接。
4.重複以上過程,修改所有secondary
修改shard叢集的存儲引擎到WiredTiger
考慮:這個過程可能會有下線時間,特别是一個或者多個shard是單機的。如果修改shard的host和端口,就必須去修改shard配置。
1.停用均衡器
2.關閉第三個config server保證中繼資料是隻讀的。
3.導出第二個config server的資料
4.對于第二個config服務,建立一個新的資料目錄,給wiredtiger使用
5.停止第二個config服務
6.啟動帶wiredtiger的mongodb啟動在第二個config服務上。
7.導入之前導出的資料
8.關閉第二個config服務,保證中繼資料隻讀
9.啟動第三個config server服務,并按3-7步驟執行
10.對于第一個config server,并按3-7步驟執行
11.啟動第二個config server
12.啟動均衡器
WiredTiger使用checkpoint來提供記憶體和磁盤上的一緻性資料視窗,允許MongoDB從最近的checkpoint恢複。如果mongodb出現異常退出,那麼journaling會被用來恢複資料。
journal恢複資料過程:
1.檢視資料檔案找到最後一次checkpoint标示
2.在journal檔案中查找比對最後一次checkpoint
3.從最後一次checkpoint開始應用journal檔案
journal過程
當啟動Journal,WiredTiger為每個用戶端的寫入記錄一條日志。内部修改操作也會記錄日志。比如update了一個文檔可能會導緻索引修改,WiredTiger會建立一個日志記錄其中包括文檔和相關索引的修改。
MongoDB為WiredTiger建立了journal記錄的cache。線程協調的配置設定和複制自己部分的buffer。所有journal記錄最多128KB的buffer。
在以下狀況下WiredTiger同步journal buffer:
1.每50毫秒
2.MongoDB發生checkpoint,checkpoint每60秒或者journal資料達到2GB。
3.如果寫入操作敏感為j:true,WiredTiger強制同步journal檔案
4.因為mongodb使用journal檔案最多為100MB,當WiredTiger建立新檔案時,同步之前檔案的緩存。
Journal檔案
對于journal檔案,MongoDB建立一個子目錄journal在dbpath下面。WiredTiger journal檔案被指令為WiredTigerLog.<sequence>,<sequence>會用0填充。
每個寫入操作有一個記錄,每個記錄包含唯一的識别符。
MongoDB使用snappy壓縮journal資料。
最小的WiredTiger的日志為128位元組,如果小于就不再壓縮。
WiredTiger的journal檔案最大限制為100MB,一旦超過會建立一個新的journal檔案。
WiredTiger會自動删除來的journal檔案,隻維護最近checkpoint以來的journal檔案。
WiredTiger會預配置設定journal檔案。
使用MMAPv1,當寫操作發生,MongoDB更新記憶體視窗。如果啟動了journal,MongoDB會先把記憶體修改記錄到journal檔案。如果MongoDB在送出資料修改前發生中斷或者出現錯誤,MongoDB可以使用journal檔案,維護資料一緻性。
MongoDB存儲引擎層有2個内部資料的視窗,Private view用來寫入到,shared view用來寫入到資料檔案。
1.MongoDB先把修改資料寫入到private view
2.MongoDB然後把這些修改寫入到journal檔案上,大概100毫秒一次。MongoDB以組送出的方式吧這些修改寫入到檔案。組送出可以最小化性能影響。寫入到檔案炒作是原子的,保證journal檔案的一緻性。也可以通過storage.journal.commitIntervalMs來設定。
3.journal送出完之後,MongoDB把修改寫入到shared view
4.最後,MongoDB把在shared view上的修改應用到資料檔案上。預設應用間隔是60s。作業系統也可以選擇比60s頻率更高的,特别是可用記憶體低的情況下。可以通過設定參數來決定重新整理頻率,storage.syncPeriodSecs。
如果MongoDB crash沒有寫資料檔案,jrounal會以重放這些修改到shared view最後寫入到資料檔案。
一旦journal操作應用到了shared view并且重新整理到了磁盤,MongoDB要求超重系統重新remap到private view,介紹記憶體使用。
當啟動了journal,MongoDB在dbpath下建立一個子目錄journal。
Journal檔案包含日志先行的,每個journal項描述了data file中的修改。Journal檔案是追加日志的。當journal檔案有1GB的資料,MongoDB會建立一個新的journal檔案。如果使用了storage.smallFiles選項那麼每個檔案的大小被限制為128MB。
Lsn檔案包含最後一次mongodb重新整理到資料檔案的時間。
一旦mongodb應用了所有某個journal檔案到資料檔案,那麼這個檔案就可以被重用。
除非你每秒寫入一些位元組,journal目錄隻要2,3個journal檔案。
幹淨關閉删除所有journal目錄的檔案。Crash的話journal目錄就有檔案,當下次啟動的時候可以自動恢複。
Journal目錄
為了保證書序寫入的,最好能夠把資料檔案和journal目錄放在不同的檔案系統下。
預配置設定
mongodb可以預配置設定journal檔案,特别是當mongod程序覺得預配置設定會比建立新的個更高效的時候。
根據檔案系統,可以在第一次啟動mongod,啟用了journal的時候顯示的預配置設定。預配置設定可能比較花時間。
具體看:
<a href="https://docs.mongodb.org/manual/core/journaling/#journaling-and-the-in-memory-storage-engine">https://docs.mongodb.org/manual/core/journaling/#journaling-and-the-in-memory-storage-engine</a>