引言
在歷經版本號修改(2.8版本直接跳到3.0版本)和11個rc版本之后,MongoDB3.0于2015年3月3日正式發布。可以毫不夸張的說,該版本的新增特性標志著MongoDB這款典型的NoSQL數據庫已經進入了一個全新的發展階段。本文以下內容會逐個盤點3.0版本的新增特性。
?
插件式存儲引擎API
MongoDB3.0引入了插件式存儲引擎API,為第三方的存儲引擎廠商加入MongoDB提供了方便,這一變化無疑參考了MySQL的設計理念。目前除了早期的MMAP存儲引擎外,WiredTiger和RocksDB均已完成了對MongoDB的支持,前者更是在被MongoDB公司收購后更是直接引入到了MongoDB3.0版本中。插件式存儲引擎API的引入為MongoDB豐富自己武器庫以處理更多不同類型的業務提供了無限可能,內存存儲引擎、事務存儲引擎甚至Hadoop在未來都有可能接入進來。

?
WiredTiger存儲引擎
如果說插件式存儲引擎API為MongoDB3.0打造了一個武器庫,那么WiredTiger絕對是武器庫中第一枚也是最重要的一枚重磅炸彈。因為MMAP存儲引擎自身的天然缺陷(耗費磁盤空間和內存空間且難以清理,庫級別鎖),MongoDB為數據庫運維人員帶來了極大痛苦,甚至一部分人已經開始轉向TokuMX,盡管后者目前也不甚穩定。意識到這一問題的MongoDB,做出了有錢任性的決定,直接收購存儲引擎廠商WiredTiger,將WiredTiger存儲引擎集成進3.0版本(僅在64位版本中提供)。那么這款走到聚光燈下的存儲引擎究竟具備哪些值得期待的特性呢?
?
1、文檔級別并發控制
WiredTiger通過MVCC實現文檔級別的并發控制,即文檔級別鎖。這就允許多個客戶端請求同時更新一個集合內存的多個文檔,再也不需要在排隊等待庫級別的寫鎖。這在提升數據庫讀寫性能的同時,大大提高了系統的并發處理能力。關于這一點的效果從監控工具mongostat就可以直接體現出來,舊版本的監控指標會有lockeddb這一項(該項指標過高是mongo使用人員的一大痛點啊),而新版的mongostat已經看不到了。

?
MongoDB 2.4.12版本
| 1 | $/home/mongodb/mongodb-linux-x86_64-2.4.12/bin/mongostat?–port55060 |
| 1 2 3 4 | insert?query?update?delete?getmore?command?flushes?mapped?vsize?resfaults?locked?db?idxmiss?%?qr|qw?ar|aw?netIn?netOut?conntime*0?*0?*0?*0?0?1|0?0?18g?18.3g?16.1g?0?ycsb:0.0%?0?0|00|0?62b?2k?1?13:04:01*0?*0?*0?*0?0?1|0?0?18g?18.3g?16.1g?0?ycsb:0.0%?0?0|00|0?62b?2k?1?13:04:02*0?*0?*0?*0?0?1|0?0?18g?18.3g?16.1g?0?ycsb:0.0%?0?0|00|0?62b?2k?1?13:04:03 |
?
MongoDB 3.0 rc8版本
| 1 | $/home/mongodb/mongodb-linux-x86_64-3.0.0-rc8/bin/mongostat?–port55050 |
| 1 2 3 4 | insert?query?update?delete?getmore?command?%?dirty?%?used?flushesvsize?res?qr|qw?ar|aw?netIn?netOut?conntime*0?*0?*0?*0?0?1|0?0.0?42.2?0?30.6G?30.4G?0|0?0|0?79b?16k?113:02:38*0?*0?*0?*0?0?1|0?0.0?42.2?0?30.6G?30.4G?0|0?0|0?79b?16k?113:02:39*0?*0?*0?*0?0?1|0?0.0?42.2?0?30.6G?30.4G?0|0?0|0?79b?16k?113:02:40 |
?
2、磁盤數據壓縮
WiredTiger支持對所有集合和索引進行Block壓縮和前綴壓縮(如果數據庫啟用了journal,journal文件一樣會壓縮),已支持的壓縮選項包括:不壓縮、Snappy壓縮和Zlib壓縮。這為廣大Mongo使用者們帶來了又一福音,因為很多Mongo數據庫都是因為MMAP存儲引擎消耗了過多的磁盤空間而不得已進行擴容。其中Snappy壓縮為數據庫的默認壓縮方式,用戶可以根據業務需求選擇適合的壓縮方式。理論上來說,Snappy壓縮速度快,壓縮率OK,而Zlib壓縮率高,CPU消耗多且速度稍慢。當然,只要選擇使用壓縮,Mongo肯定會占用更多的CPU使用率,但是考慮到Mongo本身并不是十分耗CPU,所以啟用壓縮完全是值得的。


?
此外,WiredTiger存儲方式上也有很大改進。舊版本Mongo在數據庫級別分配文件,數據庫中的所有集合和索引都混合存儲在數據庫文件中,所以即使刪掉了某個集合或者索引,占用的磁盤空間也很難及時自動回收。WiredTiger在集合和索引級別分配文件,數據庫中的所有集合和索引均存儲在單獨的文件中,集合或者索引刪除后,對應的存儲文件隨即刪除。當然,因為存儲方式不同,低版本的數據庫無法直接升級到WiredTiger存儲引擎,只能通過導出導入數據的方式來實現。
?
MongoDB 2.4.12版本
| 1 | [mongodb@mongo-data-emergency-001.m6.momo.com?mongodb_2_4_12]$ll |
| 1 2 3 4 | drwxrwxr-x?3?mongodb?mongodb?4096?2月?25?19:03local-rwxrwxr-x?1?mongodb?mongodb?6?2月?25?19:04mongod.lockdrwxrwxr-x?2?mongodb?mongodb?4096?2月?27?18:30_tmpdrwxrwxr-x?3?mongodb?mongodb?4096?2月?27?18:39ycsb |
| 1 | [mongodb@mongo-data-emergency-001.m6.momo.com?mongodb_2_4_12]$?ll?ycsb/ |
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | drwxrwxr-x?2?mongodb?mongodb?4096?2月?27?18:39_tmp-rw——-?1?mongodb?mongodb?67108864?2月?27?18:57ycsb.0-rw——-?1?mongodb?mongodb?134217728?2月?27?18:57ycsb.1-rw——-?1?mongodb?mongodb?2146435072?2月?27?18:57ycsb.10-rw——-?1?mongodb?mongodb?2146435072?2月?27?18:57ycsb.11-rw——-?1?mongodb?mongodb?2146435072?2月?27?18:57ycsb.12-rw——-?1?mongodb?mongodb?2146435072?2月?27?18:39ycsb.13-rw——-?1?mongodb?mongodb?268435456?2月?27?18:57ycsb.2-rw——-?1?mongodb?mongodb?536870912?2月?27?18:57ycsb.3-rw——-?1?mongodb?mongodb?1073741824?2月?27?18:57ycsb.4-rw——-?1?mongodb?mongodb?2146435072?2月?27?18:57ycsb.5-rw——-?1?mongodb?mongodb?2146435072?2月?27?18:57ycsb.6-rw——-?1?mongodb?mongodb?2146435072?2月?27?18:57ycsb.7-rw——-?1?mongodb?mongodb?2146435072?2月?27?18:57ycsb.8-rw——-?1?mongodb?mongodb?2146435072?2月?27?18:57ycsb.9-rw——-?1?mongodb?mongodb?16777216?2月?27?18:40ycsb.ns |
?
Mongo 3.0 rc8版本
| 1 | [mongodb@mongo-data-emergency-001.m6.momo.com?mongodb_3_0_0]$ll |
| 1 2 3 4 5 6 7 8 9 10 11 | drwxrwxr-x?2?mongodb?mongodb?4096?2月?28?18:32local-rw-rw-r–?1?mongodb?mongodb?36864?3月?21?13:41_mdb_catalog.wt-rwxrwxr-x?1?mongodb?mongodb?6?2月?28?18:32mongod.lock-rw-rw-r–?1?mongodb?mongodb?36864?3月?21?13:42sizeStorer.wt-rw-rw-r–?1?mongodb?mongodb?95?2月?28?18:32storage.bson-rw-rw-r–?1?mongodb?mongodb?49?2月?28?18:32WiredTiger-rw-rw-r–?1?mongodb?mongodb?433?2月?28?18:32WiredTiger.basecfg-rw-rw-r–?1?mongodb?mongodb?21?2月?28?18:32WiredTiger.lock-rw-rw-r–?1?mongodb?mongodb?921?3月?21?13:41WiredTiger.turtle-rw-rw-r–?1?mongodb?mongodb?53248?3月?21?13:41WiredTiger.wtdrwxrwxr-x?2?mongodb?mongodb?4096?3月?21?13:41ycsb |
| 1 | [mongodb@mongo-data-emergency-001.m6.momo.com?mongodb_3_0_0]$?ll?ycsb/ |
| 1 2 3 4 5 | -rw-rw-r–?1?mongodb?mongodb?19314257920?2月?2819:16?collection-4–1318477584648278106.wt-rw-rw-r–?1?mongodb?mongodb?602112?3月?2113:40?collection-6–1318477584648278106.wt-rw-rw-r–?1?mongodb?mongodb?262598656?2月?2818:53?index-5–1318477584648278106.wt-rw-rw-r–?1?mongodb?mongodb?827392?3月?2113:40?index-7–1318477584648278106.wt-rw-rw-r–?1?mongodb?mongodb?1085440?3月?2113:41?index-8–1318477584648278106.wt |
?
3、可配置內存使用上限
WiredTiger支持內存使用容量配置,用戶通過storage.wiredTiger.engineConfig.cacheSizeGB參數即可控制MongoDB所能使用的最大內存,該參數默認值為物理內存大小的一半。這也為廣大Mongo使用者們帶來了又一福音,MMAP存儲引擎消耗內存是出了名的,只要數據量夠大,簡直就是有多少用多少。
?
MMAPv1存儲引擎提升
MongoDB3.0出了引入WiredTiger外,對于原有的存儲引擎MMAP也進行了一定的完善,該存儲引擎依然是3.0版的默認存儲引擎。遺憾的是改進后的MMAP存儲引擎依舊在數據庫級別分配文件,數據庫中的所有集合和索引都混合存儲在數據庫文件中,所以磁盤空間無法及時自動回收的問題如故。
?
1、鎖粒度由庫級別鎖提升為集合級別鎖
這在一定程度上也能夠提升數據庫的并發處理能力。
?
2、文檔空間分配方式改變
在MMAP存儲引擎中,文檔按照寫入順序排列存儲。如果文檔更新后長度變長且原有存儲位置后面沒有足夠的空間放下增長部分的數據,那么文檔就要移動到文件中的其他位置。這種因更新導致的文檔位置移動會嚴重降低寫性能,因為一旦文檔發生移動,集合中的所有索引都要同步修改文檔新的存儲位置。
?
MMAP存儲引擎為了減少這種情況的發生提供了兩種文檔空間分配方式:基于paddingFactor(填充因子)的自適應分配方式和基于usePowerOf2Sizes的預分配方式,其中前者為默認方式。第一種方式會基于每個集合中文檔更新歷史計算文檔更新的平均增長長度,然后在新文檔插入或舊文檔移動時填充一部分空間,如當前集合paddingFactor的值為1.5,那么一個大小為200字節的文檔插入時就會自動在文檔后填充100個字節的空間。第二種方式則不考慮更新歷史,直接為文檔分配2的N次方大小的存儲空間,如一個大小同樣為200字節的文檔插入時直接分配256個字節的空間。
?
MongoDB3.0版本中的MMAPv1拋棄了基于paddingFactor的自適應分配方式,因為這種方式看起來很智能,但是因為一個集合中的文檔的大小不一,所以經過填充后的空間大小也不一樣。如果集合上的更新操作很多,那么因為記錄移動后導致的空閑空間會因為大小不一而難以重用。目前基于usePowerOf2Sizes的預分配方式成為默認的文檔空間分配方式,這種分配方式因為分配和回收的空間大小都是2的N次方(當大小超過2MB時則變為2MB的倍數增長),因此更容易維護和利用。如果某個集合上只有insert或者in-placeupdate,那么用戶可以通過為該集合設置noPadding標志位,關閉空間預分配。

?
復制集改進
?
1、復制集成員增長
MongoDB3.0的復制集成員的最大個數由之前的12個增長為50個,但能夠投票的最大成員個數依然為7個,而相應的getLastError中的 w:“majority” 項也僅代表投票節點的大多數。
?
2、Primary節點StepDown處理方式變化
在復制集中通過replSetStepDown命令可以使得當前的Primary節點退位,重新選舉新的Primay節點。MongoDB3.0在StepDown的處理方式上做了如下修改:
1)在Primary退位之前,會首先中斷某些耗時較長的用戶操作如創建索引、寫操作、Mapreduce任務等;
2)為了防止數據回滾,Primary節點在退位之前會等待一個可被選舉的Secondary節點同步到最新數據,而舊版本中Primary節點只要有Secondary節點的數據同步到10秒以內就退位;
3)同時replSetStepDown命令新增了一個secondaryCatchUpPeriodSecs參數,用戶可以指定Primary節點等待有Secondary節點的數據同步到該參數指定的秒數內就退位。
?
分片集群改進
?
1、新增工具函數 sh.removeTagRange()
舊版本中只有sh.addTagRange(),如果要刪除tagRange只能手工到config.tags集合中刪除。
?
2、提供更可預測的Read Preference處理
新版本中mongos實例在執行讀操作時不再將連接固定在復制集成員上,而是對每個讀操作都會重新評估ReadPreference。這樣當Read Preference修改時,其行為更容易預測。
?
3、為chunk遷移提供writeConcern設置
新版本針對均衡器為moveChunk和cleanupOrphaned這兩個涉及到chunk遷移的命令提供了writeConcern參數。
?
4、增加均衡器狀態顯示
新版本中通過sh.status()可以看到均衡器的狀態信息。
?
其他改動
?
1、優化explan函數
新版本explain函數可以支持count,find,group,aggregate,update,remove等操作的查詢計劃顯示,結果更全面更精細。
?
2、重寫mongodb工具
新版本所有mongodb自帶工具均使用Go語言重寫,特別是在mongodump和mongorestore添加了并行機制,這樣可以大大加快數據的導出和導入。
?
3、日志輸出控制
新版本中將日志分為不同的模塊,其中包括ACCESS、COMMAND、CONTROL、GEO、INDEX、NETWORK、QUERY、REPL、SHARDING、STORAGE、JOURNAL和WRITE等。用戶可以動態調整每個模塊的日志級別,這無疑更有利于系統問題診斷。
?
4、 索引構建優化
后臺索引建立過程中,不能進行刪庫刪表刪索引操作,且后臺索引建立過程不會因此自動中斷。另外,使用createIndexes命令可以同時建立多個索引,并且只掃描一遍數據,提升了建索引的效率。
?
總結
?
以上僅列出了MongoDB 3.0的一些主要特性和修改,如果希望了解更多可以查看MongoDB 3.0的Release-Notes。總體來看,MongoDB3.0提供了較多令人驚喜的新特性,也使人們更加看好其未來的發展。
?
參考資料鏈接
?
MongoDB3.0官方Release-Notes:http://docs.mongodb.org/manual/release-notes/3.0/
北京Mongo用戶組第二次線下活動PPT:http://www.mongoing.com/archives/543
http://blog.chinaunix.net/xmlrpc.php?r=blog/article&id=4865696&uid=15795819
本文轉自UltraSQL51CTO博客,原文鏈接:?http://blog.51cto.com/ultrasql/1737684,如需轉載請自行聯系原作者