MongoDB 初見指南

技術若只如初見,那麼還會踩坑麼?

在系統引入 MongoDB 也有幾年了,一開始是由於 MySQL 中有單表記錄增加太快(天天幾千萬條吧)容易拖慢 MySQL 的主從複製。而這類數據增加迅速的流水錶,對數據一致性也沒那麼高要求,並且業務上也不須要關聯查詢它,就考慮分出去。爲何是 MongoDB?剛巧遇上公司 DBA 團隊引入了這個數據庫,有人幫助運維,對業務團隊就成了一個天然的選擇。不過對於任何技術產品你若是要把它用在生產環境上,最好肯定對它的架構和運做機理有個全面的理解。html

形態

MongoDB 是一種 NoSQL 數據庫,它在數據存儲的形態上和 MySQL 這類關係數據庫有本質區別。MongoDB 存儲的基本對象是 Document,因此咱們把它稱爲一種文檔數據庫,而文檔的集合則組成了 Collection。與 SQL 的概念類比,Collection 對應於 Table 而 Document 對應於 Row。Document 使用一種 BSON(Binary JSON)結構來表達,JSON 你們都熟悉,像下面這樣。算法

Document 在內部是如何存儲的?每一個 Document 被保存在一個 Record 中。Record 至關於 MongoDB 內部分配的一塊空間,除了保存 Document 的內容可能還會預留一些填充的額外空間。對於寫入後的 Document 若是還會更新,可能致使 Document 長度增長,就能夠利用上額外的填充空間來。若業務對於寫入後的 Document 不會再更新或刪除(像監控日誌、流水記錄等),能夠指定無填充的 Record 分配策略,更節省空間。mongodb

瞭解了 Document 形態的基礎上,咱們再說點針對 Document 的訪問操做。新的 WiredTiger 存儲引擎提供了 Document 級別的併發操做,因此併發性能有所改善。另外 MongoDB 僅對單一 Document 提供事務的 ACID 保障,若是一個操做涉及多個 Document 則不能保證事務特性。不一樣的業務數據對事務一致性的要求不一樣,因此應用開發者須要知道將數據放在不一樣的 Document 中寫入時在一致性方面可能的影響。詳細的操做 API 直接看官方文檔,不贅述了。shell

安全

這裏的安全指的數據安全,安全就是說數據被安全的保存好了,不會丟失。關於 MongoDB 數據安全在早期的版本(1.x)引起了不少爭論。(能夠看參考[2])數據庫

安全和效率實際上是相互制約的,越安全則效率越低,越高效則越不安全。MongoDB 的設計場景考慮的是應對大量的數據寫入和查詢,而數據的重要性相對沒那麼高。因此 MongoDB 的默認設置在安全和效率之間,更偏向效率。安全

咱們先看下一個 Document 被寫入到 MongoDB 後它內部的處理方式。MongoDB 的 API 提供了不一樣安全級別的寫入選項來讓使用方根據其數據性質靈活的選擇。網絡

Write To Buffer Without ACK架構

這個模式下 MongoDB 是不確認寫請求的,Client 端調用驅動寫入後若沒有網絡錯誤就認爲成功,實際到底寫入成功沒有是不肯定的。即便網絡沒有問題,數據到達 MongoDB 後它先保存在內存 Buffer 中,再異步寫入 Journaling 日誌,這中間有 100ms(默認值) 的落盤(寫入磁盤)時間窗口。通常數據庫的設計都是先寫 Journaling 的流水日誌,隨後異步再寫真正的數據文件到磁盤,這個隨後可能就比較長了,MongoDB 是 60 秒或者 Journaling 日誌達到 2G。併發

Write To Buffer With ACKapp

這個比上一種模式稍微好一點,MongoDB 收到寫入請求,先寫入內存 Buffer 後回發 Ack 確認。Client 端能確保 MongoDB 收到了寫入數據,但依然有短暫的 Journaling 日誌落盤時差致使潛在的數據丟失可能。

Write To Journaling With ACK

這個模式確保至少寫入 Journaling 日誌後纔回發 Ack 確認,Client 端能確保數據至少寫入磁盤了,安全性較高。

Write To Replica Buffer With ACK

這個模式是針對多副本集的,爲了提高數據安全性,除了及時寫入磁盤也能夠經過寫多個副原本提高。在這個模式下,數據至少寫入 2 個副本的內存 Buffer 中才回發 Ack 確認。雖然都在內存 Buffer 中,但兩個實例在落盤短暫的 100ms 時差中同時故障的機率很低,因此安全性有所提高。

明白了不一樣的寫入模式選項,咱們才能更好的真對數據的性質選擇合適的安全級別。後面效率一節咱們再分析不一樣寫入模式下的效率差別。

容量

在考慮 MongoDB 總體的存儲容量前,先考慮做爲基本單元的 Document 的容量。Document 這種 JSON 形態天生會帶來數據存儲冗餘,主要是 field 屬性每一個 Document 都會保存一遍。目前 3.2 版本的 MongoDB 已經將新的 WiredTiger 做爲默認存儲引擎,它提供了壓縮功能,有兩種壓縮形式:

  • Snappy 默認壓縮算法,在壓縮率和 CPU 開銷之間取得平衡。

  • Zlib 更高的壓縮率,但也帶來更高的 CPU 開銷。

而每一個 Document 依然有最大容量限制,不能無限增加下去,這個限制目前是 16MB。那麼我要存大於 16MB 的文件怎麼辦,MongoDB 提供了 GridFS 來存儲超過 16MB 大小的文件。以下圖所示,一個大文件被拆分紅小的 File Chunk,每一個 Chunk 大小 255KB,並存放在一個 Document 中。GridFS 使用了 2 個 Collection 來分別存放文件 Chunk 和文件元數據。

單機的容量老是受限於磁盤大小,而 MongoDB 解決方案依然是分片化。是用更多的機器來提供更大的容量,分片集羣採用代理模式(《Redis 集羣的合縱與連橫》一文中寫過這類模式),以下圖。

而每一個分片上的數據又以 Chunk 的形式組織(相似於 Redis Cluster 的 Slot 概念),以便於集羣內部的數據遷移和再平衡。比較容易混淆的是這裏的 Chunk 不是前面 GridFS 裏提到的 Chunk,它們的關係大概以下圖(吐槽下,幹嗎要用同名的術語來表達徹底不一樣的概念)。

支持水平擴展和數據再平衡功能的 MongoDB Cluster 基本上數據容量就再也不是個問題了。

效率

前面「安全」一節列舉了不一樣的寫入模式,咱們看下在這些不一樣模式下寫入的效率如何。因爲官方沒有提供基準性能測試數據,下面的數據來自參考文獻[5]一個從 2009 年開始使用 MongoDB 的專業技術公司博客分享的寫入基準測試數據。我這裏根據數據結果作一些分析總結,下面是測試結果數據的表格和圖形展現。

  • w=0, Write To Buffer Without ACK

  • w=1, Write To Buffer With ACK

  • j=1, Write To Journaling With ACK

  • w=2, Write To Replica Buffer With ACK

測試類型多了一項將 Journaling 日誌放在 SSD 和機械硬盤上的差別,這讓咱們能夠直觀的感覺 SSD 和機械硬盤在順序寫狀況下的性能差別。對於機械硬盤最大的性能制約是在磁頭移動,因此 MongoDB 官方文檔也建議將 Journaling 日誌和數據文件放在不一樣的磁盤上。保證順序寫 Journaling 日誌的磁頭不會被隨機寫數據文件影響,而數據文件的寫入是經過內存 buffer 緩衝的一個異步過程,對交互性能延遲的影響不大。

根據測試結果數據看,有無 Ack 之間響應延時相差一倍,基本就是多了一個網絡傳輸的延時等待時間。開啓 Journaling 保證及時落盤,不管是 SSD 仍是機械硬盤,這個延時都上升了 2 個數量級,翻了百倍,而 SSD 的順序寫比機械硬盤平均快 3 倍。而寫雙副本的平均延時比我預期高了很多,應該說延時的波動很大,不像寫磁盤延時最小、最大和平均的值很是接近。理論上寫雙副本不落盤的狀況延時只應該比單一狀況多一倍的網絡開銷外加部份程序開銷,而實際測試數據顯示遠遠高於預期並且延時波動範圍大了不少。這種模式下 MongoDB 延時表現波動範圍太大,不夠穩定,具體究竟是實現上的缺陷仍是測試不夠準確,就不得而知。並且當時測試的版本是 2.4.1 不知道最新的 3.2 版本如何,若是採用這類寫模式,可模擬本身生產環境實測得出結論。

至於讀取性能是無法作基準測試了,不一樣的文檔模型,選擇不一樣的查詢條件,性能均可能不一樣。雖然 MongoDB 是 Schemaless 的,但不意味着不須要對文檔的 Schema 進行設計,不一樣的 Schema 設計對性能的影響仍是很大的。

總結

面臨一個新的技術產品或系統,「形態」是針對這個產品或系統最獨特部分的描述,屬於核心模型。而「安全」、「容量」、「效率」三個核心維度全面反應了一個技術產品或系統的不一樣設計和實現考慮,可類於比機械設計中的「三視圖」。對於初次面對一個新的技術產品或系統,這是一個適合的切入點來幫助作初步的技術決策,而後跟着進一步的實踐測試來驗證思考和理解,這樣才能更好的理解和用好現有技術,作一個合格的技術拿來主義者。

參考

1] MongoDB Doc. [MongoDB Manual
2] MongoDB White Paper. [MongoDB Architecture Guide
3] 陳皓. [千萬別用MongoDB?真的嗎?. 2011.11
4] David Mytton. [Does everyone hate MongoDB?. 2012.09
5] David Mytton. [MongoDB Benchmarks. 2012.08
6] David Mytton. [MongoDB Schema Design Pitfalls. 2013.02


寫點文字,畫點畫兒,「瞬息之間」一切都變了。以爲不錯,可長按或掃描二維碼關注。
圖片描述

相關文章
相關標籤/搜索