9. 存儲 9. 存儲... 1 9.1 存儲引擎... 1 9.1.1 WiredTiger存儲引擎... 1 9.1.1.1 文檔級別併發... 1 9.1.1.2 快照和檢查點... 2 9.1.1.3 Journaling. 2 9.1.1.4 壓縮... 2 9.1.1.5 記憶體使用... ...
9. 存儲
9.1 存儲引擎
存儲引擎是資料庫的一個組件用於管理數據存儲。Mongodb支持多存儲引擎,不同的存儲引擎對於指定負荷可能會有更好的性能。
WiredTiger在Mongodb 3.2之後作為預設的存儲引擎,能夠很好的適應很多負荷。WiredTiger提供文檔級別的併發模型,檢查點,壓縮,和其他特性。
MMAPv1是Mongodb老的存儲引擎在mongodb 3.2之前是預設的存儲引擎。
In-Memory Storage Engine在Mongodb 企業版可用。和其他存儲引擎不同數據是存放在記憶體減少數據延遲。
9.1.1 WiredTiger存儲引擎
從3.0開始已經在64位系統上可用。
在3.2版本中WiredTiger存儲引擎為預設存儲引擎。如果沒有指定--storageEngine或者storage.engine會自動決定存儲引擎的使用並且存放在storage.dbPath下。
9.1.1.1 文檔級別併發
WiredTiger使用文檔級別併發控制寫入操作。這樣多個客戶端可以同時對不同的文檔進行修改。對於很多讀寫操作WiredTiger使用最優的併發控制。WiredTiger在全局,資料庫,collection上使用意向鎖。當存儲引擎發現2個衝突操作,一個操作會出現寫入重提,需要顯示的重試這個操作。
一些全局操作,通常執行時間短的涉及到多個資料庫的,還是會使用全局鎖。對於drop collection還是會有資料庫x鎖。
9.1.1.2 快照和檢查點
WiredTiger使用多版本併發控制(MVCC),在操作之前,WiredTiger提供一個數據快照。快照表示記憶體資料庫的視窗。
當寫入磁碟,WiredTiger寫入所有的快照中的數據到磁碟。新的固化數據被當做數據文件的checkpoint。
MongoDB在每60秒或者2GB journal數據創建checkpoint。
當在創建新的檢查點,老的檢查點還是可用。如果MongDB在寫入checkpoint的時候發生錯誤或者中斷,MongoDB可以使用最後一次有效的checkpoint。
當WiredTiger元數據表自動更新引用新的檢查點,新的檢查點變成可用,並且持久。一旦新的checkpoint可用,老的checkpoint就被釋放。
如果沒有開啟journaling,mongodb會從最後一次checkpoint恢復,checkpoint之後的恢復需要用到journaling。
9.1.1.3 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之間不可預見的退出。對於複製集,複製進程可以滿足持久性要求。
9.1.1.4 壓縮
使用WiredTiger,MongoDB支持對所有collection和index 進行壓縮。壓縮可以減少存儲的使用但是會花費一點cpu。
預設,WiredTiger使用塊壓縮,使用snappy壓縮方式壓縮所有collection,對所有索引使用首碼壓縮。
對於collection,塊壓縮也可以使用zlib。
設置storage.wiredTiger.collectionConfig. blockCompressor。
對於index,取消首碼壓縮,storage.wiredTiger.indexConfig.prefixCompression
壓縮設置可以在每個collection或者索引上在創建時設置。對於很多負荷預設壓縮設置平衡了存儲效率和處理要求。
9.1.1.5 記憶體使用
使用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.啟動均衡器
9.1.2 MMAPv1存儲引擎
具體看:https://docs.mongodb.org/manual/core/mmapv1/
9.1.3 In-Memory存儲引擎
具體看:https://docs.mongodb.org/manual/core/inmemory/
9.2 Journaling
9.2.1 Journaling和WiredTiger引擎
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文件。
9.2.2 journal和MMAPv1引擎
使用MMAPv1,當寫操作發生,MongoDB更新記憶體視窗。如果啟動了journal,MongoDB會先把記憶體修改記錄到journal文件。如果MongoDB在提交數據修改前發生中斷或者出現錯誤,MongoDB可以使用journal文件,維護數據一致性。
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文件
當啟動了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的時候顯示的預分配。預分配可能比較花時間。
9.2.3 Journal和in-memory存儲引擎
具體看:
https://docs.mongodb.org/manual/core/journaling/#journaling-and-the-in-memory-storage-engine