1. 程式人生 > >MongoDB儲存引擎選擇

MongoDB儲存引擎選擇

MongoDB儲存引擎選擇

  1. MongoDB儲存引擎構架

外掛式儲存引擎, MongoDB 3.0引入了外掛式儲存引擎API,為第三方的儲存引擎廠商加入MongoDB提供了方便,這一變化無疑參考了MySQL的設計理念。目前除了早期的MMAP儲存引擎外,WiredTiger和RocksDB均 已完成了對MongoDB的支援,前者更是在被MongoDB公司收購後更是直接引入到了MongoDB 3.0版本中。外掛式儲存引擎API的引入為MongoDB豐富自己武器庫以處理更多不同型別的業務提供了無限可能,記憶體儲存引擎、事務儲存引擎甚至 Hadoop在未來都有可能接入進來。

圖1-1 MongoDB <= 2.6 儲存引擎構架

圖1-2 MongoDB 3.0 儲存引擎構架

  1. MongoDB儲存引擎說明
    • WiredTiger

如 果說外掛式儲存引擎API為MongoDB 3.0打造了一個武器庫,那麼WiredTiger絕對是武器庫中第一枚也是最重要的一枚重磅炸彈。因為MMAP儲存引擎自身的天然缺陷(耗費磁碟空間和 記憶體空間且難以清理,庫級別鎖),MongoDB為資料庫運維人員帶來了極大痛苦,甚至一部分人已經開始轉向TokuMX,儘管後者目前也不甚穩定。意識到這一問題的MongoDB,做出了有錢任性的決定,直接收購儲存引擎廠商WiredTiger,將WiredTiger儲存引擎整合進3.0版本(僅在64位版本中提供)。那麼這款走到聚光燈下的儲存引擎究竟具備哪些值得期待的特性呢?

  • 文件級別併發控制

WiredTiger 通過MVCC實現文件級別的併發控制,即文件級別鎖。這就允許多個客戶端請求同時更新一個集合記憶體的多個文件,再也不需要在排隊等待 庫級別的寫鎖。這在提升資料庫讀寫效能的同時,大大提高了系統的併發處理能力。關於這一點的效果從監控工具mongostat就可以直接體現出來,舊版本 的監控指標會有locked db這一項(該項指標過高是mongo使用人員的一大痛點啊),而新版的mongostat已經看不到了。

圖2.1.1 文件級別併發控制

  • 磁碟資料壓縮

WiredTiger 支援對所有集合和索引進行Block壓縮和字首壓縮(如果資料庫啟用了journal,journal檔案一樣會壓縮),已支援的壓 縮選項包括:不壓縮、Snappy壓縮和Zlib壓縮。這為廣大Mongo使用者們帶來了又一福音,因為很多Mongo資料庫都是因為MMAP儲存引擎消 耗了過多的磁碟空間而不得已進行擴容。其中Snappy壓縮為資料庫的預設壓縮方式,使用者可以根據業務需求選擇適合的壓縮方式。理論上來說,Snappy 壓縮速度快,壓縮率OK,而Zlib壓縮率高,CPU消耗多且速度稍慢。當然,只要選擇使用壓縮,Mongo肯定會佔用更多的CPU使用率,但是考慮到 Mongo本身並不是十分耗CPU,所以啟用壓縮完全是值得的。

圖2.1.1-1 磁碟資料壓縮 snappy

圖2.1.1-1 磁碟資料壓縮 zlib

  • 儲存方式改變

此 外,WiredTiger儲存方式上也有很大改進。舊版本Mongo在資料庫級別分配檔案,資料庫中的所有集合和索引都混合儲存在資料庫檔案中,所以即 使刪掉了某個集合或者索引,佔用的磁碟空間也很難及時自動回收。WiredTiger在集合和索引級別分配檔案,資料庫中的所有集合和索引均儲存在單獨的 檔案中,集合或者索引刪除後,對應的儲存檔案隨即刪除。當然,因為儲存方式不同,低版本的資料庫無法直接升級到WiredTiger儲存引擎,只能通過導 出匯入資料的方式來實現。

  • 可配置記憶體使用上限

WiredTiger 支援記憶體使用容量配置,使用者通過storage.wiredTiger.engineConfig.cacheSizeGB引數即可 控制MongoDB所能使用的最大記憶體,該引數預設值為實體記憶體大小的一半。這也為廣大Mongo使用者們帶來了又一福音,MMAP儲存引擎消耗記憶體是出 了名的,只要資料量夠大,簡直就是有多少用多少。

  • MMAPv1

MongoDB 3.0出了引入WiredTiger外,對於原有的儲存引擎MMAP也進行了一定的完善,該儲存引擎依然是3.0版的預設儲存引擎。遺憾的是改進後的 MMAP儲存引擎依舊在資料庫級別分配檔案,資料庫中的所有集合和索引都混合儲存在資料庫檔案中,所以磁碟空間無法及時自動回收的問題如故。

  • 鎖粒度由庫級別鎖提升為集合級別鎖

這在一定程度上也能夠提升資料庫的併發處理能力。

  • 文件空間分配方式改變

在 MMAP儲存引擎中,文件按照寫入順序排列儲存。如果文件更新後長度變長且原有儲存位置後面沒有足夠的空間放下增長部分的資料,那麼文件就要移動到檔案 中的其他位置。這種因更新導致的文件位置移動會嚴重降低寫效能,因為一旦文件發生移動,集合中的所有索引都要同步修改文件新的儲存位置。

MMAP 儲存引擎為了減少這種情況的發生提供了兩種文件空間分配方式:基於paddingFactor(填充因子)的自適應分配方式和基於 usePowerOf2Sizes的預分配方式,其中前者為預設方式。第一種方式會基於每個集合中文件更新歷史計算文件更新的平均增長長度,然後在新文件 插入或舊文件移動時填充一部分空間,如當前集合paddingFactor的值為1.5,那麼一個大小為200位元組的文件插入時就會自動在文件後填充 100個位元組的空間。第二種方式則不考慮更新歷史,直接為文件分配2的N次方大小的儲存空間,如一個大小同樣為200位元組的文件插入時直接分配256個字 節的空間。

MongoDB 3.0版本中的MMAPv1拋棄了基於paddingFactor的自適應分配方式,因為這種方式看起來很智慧,但是因為一個集合中的文件的大小不一,所 以經過填充後的空間大小也不一樣。如果集合上的更新操作很多,那麼因為記錄移動後導致的空閒空間會因為大小不一而難以重用。目前基於 usePowerOf2Sizes的預分配方式成為預設的文件空間分配方式,這種分配方式因為分配和回收的空間大小都是2的N次方(當大小超過2MB時則 變為2MB的倍數增長),因此更容易維護和利用。如果某個集合上只有insert或者in-place update,那麼使用者可以通過為該集合設定noPadding標誌位,關閉空間預分配。

圖2.2.2 儲存引擎空間管理

  1. MongoDB儲存引擎效能對比
    • 官方資料,基於YCSB測試,WiredTiger引擎

YCSB被一些機構用來作為對幾個不同資料庫的效能測試的一個工具。YCSB功能是相當有限的,並不一定能夠告訴你所有你想了解的關於你應用程式效能方面的資訊。當然,YCSB還是相當流行的,並且MongoDB和其他一些資料庫系統的使用者也對此比較熟悉。

  • 併發量

100%寫場景:在YCSB測試中, MongoDB3.0在多執行緒、批量插入場景下較之於MongoDB2.6有大約7倍的增長。

95%讀取和5%更新的場景: WiredTiger 有4倍多的吞吐量。相比於純插入場景,效能提升沒有那麼顯著,因為寫操作只佔所有操作的5%。在MongoDB2.6中,併發控制是在資料庫級別,而且寫會阻塞讀操作,從而降低總體的併發量。通過這次測試,我們看到MongoDB 3.0更加細粒的併發性控制明顯提高了總併發量。

讀寫操作平衡的場景: MongoDB3.0有6倍的併發率。這比95%讀 的4倍提高要好一些,因為這裡有更多的寫操作。

圖3.1.1 併發量

  • 響應延遲

在效能測試中僅僅監測併發量是不夠的,還要考慮操作的響應延遲 。對許多操作的響應延遲做一個平均得來的平均響應延遲值不是一個最好的度量指標。對於想要系統有持續良好、低延時體驗的開發者來說,他們更關注在這個系統 中效能最低的操作。 高延時查詢通常用95th和99th百分位數來衡量 – 95th 百分位數表示這個數值(響應延遲)比95%的其他操作都要糟糕(慢)。(有人可能會覺得這種衡量不夠準確: 因為很多網頁請求會使用幾百個資料庫操作, 那麼很可能絕大部分使用者都會經歷到這些99th百分位數的慢響應延遲 )

在讀操作響應延遲上看到在MongoDB2.6和MongoDB3.0之間的差別是非常微小的,讀操作響應延遲很穩定的保持在1ms或者更少的數值內。然而更新操作響應延遲則有相當大的區別 。

圖3.1.2-1響應延遲,讀密集型

在這裡我們通過讀密集型的工作負荷來比較更新響應延遲的95th和99th百分位數 。在MongoDB3.0中更新延時顯著改善了,在95th和99th百分位數中幾乎減少了90%。這很重要,提高併發量不應該以更長的延時為代價,因為 這將最終降低應用程式 的使用者體驗。

圖3.1.2-1響應延遲,平衡型

在平衡的工作負荷下,更新延遲仍然保持在較低的水平 。在95th百分位數,MongoDB3.0的更新延遲比MongoDB2.6幾乎低90%,而99th百分位數則低80% 。這些改善可以給使用者帶來更好的使用體驗,更加可預測的效能。
我們相信這些針對併發量和響應延遲的測試證明了MongoDB在寫效能上有了顯著的提高。

  • 提供充足客戶端能力

大多數資料庫都是為多執行緒客戶端設計的 。通過逐步增加執行緒數來找到最佳的數量 – 增加更多執行緒直到你發現併發率停止上升或者響應時間在增加。

圖3.1.3-1多執行緒MMAP、WiredTiger吞吐量對比

圖3.1.3-1 WiredTiger吞吐量延遲對比

  • 實際測試

時間關係,本人未做相關測試,網上收錄部分測試資料;

  • 案例一

公司某個APP應用的資料庫已 經實現了日誌與業務的垂直分割,將原有的一套RAC,拆分成兩套,目前資料庫暫時還比較穩定,伺服器負載也在正常範圍內,但是現有使用者數450萬,日活躍 使用者達到100萬,每日日誌產生1000萬條記錄,100G的資料量,而目標使用者數接近1800萬,預估屆時的每日資料庫將達到6000萬/條,且需要滿 足單條記錄查詢的需求,計劃採用MongoDB來替代ORACLE RAC,現測試MongoDB WiredTiger引擎與MMAPv1引擎的寫入對比。

測試場景:插入1000萬條資料的時間消耗對比;

測試結果:MongoDB MMAPv1寫入配置:1000萬條資料寫入花費了12分鐘28秒;MongoDB WiredTiger寫入配置:1000萬條資料寫入花費了10分3秒。

  • 案例二

某專案在設計初期使用了mongodb2.6,由於開發設計失誤在mongodb中使用了一個很大的資料。而該業務每天需要全亮更新每一個文件,也就是更 新陣列欄位,這致使在ssd上依然出現了效能問題,而由於該專案已經不再更新處於維護節點並且之前的開發已離職,導致無法通過修改業務邏輯變更資料結構來 調優。

將其遷移到mongodb3.0後資料提及從202G降低到36G,同時更新效能提高五倍,完美解決了效能問題。

  • 案例三

Mongdob3.0.2的一個專案使用匯報:

之前使用18分片的mongoS叢集,用於業務的統計分析,比如404、503、請求量以及網址請求次數等等。

mongodb的使用場景為:

  • 每秒寫入2萬條資料,其中insert和update比例為3:7,全部使用upsert方法
  • 全部查詢均為統計類查詢,用於畫圖

在今年年初由於寫入併發量不斷增長到3萬條每秒,導致出現了嚴重的效能問題,現象為:

  • 寫入佇列積壓,每天大概積壓80G資料,資料延遲寫入22小時,也就是現在的資料,22小時候才能看到
  • 查詢基本不可用,無法在頁面通過統計繪圖了

在4月26號升級到了3.0.2,結果如下:

  • 寫入佇列無任何積壓,實時寫入
  • 查詢速度暴快,繪圖秒出
  • 分片減少了一半,從18個變為9個,每個分片使用2塊獨立的ssd,等於0為我們省下了18塊ssd
  • 資料總體積的變化:從3T變成了不到600G
  • 慢更新消失了(500ms以上的操作會記錄日誌)
  1. 總結

從官方資料和實際使用效果來說,WiredTiger引擎總體上勝出MMAPv1,不論從記憶體使用效率和儲存空間使用效率,還是其寫入更新效率,所以在選用MongoDB3.0以上版本時建議還是採用WiredTiger引擎。

但是需要注意一下幾點:

首先其在Windows上的效能指標不如Linux,所以搭載伺服器最好選用Linux系;

其次Journal 預設不會即時刷盤,系統宕機會丟失最多100MB Journal資料;

再有其不提供32位 支援;

本文轉自:http://blog.itfsw.com/2017/04/01/mongodb-cunchuyinqing-xuanze/