1. 程式人生 > >MongoDB的正確使用姿勢

MongoDB的正確使用姿勢

本文來自網易雲社群,轉載務必請註明出處。

MongoDB是一個非常有前途的資料庫,MongoDB官方對自己的定位是通用資料庫,其實這個定位跟MySQL有些像。雖其流行度還遠未達到MySQL的水平,但筆者有個可能不恰當的比較,MongoDB就像N年前的MySQL,隨著時間的推移,會變得越來越強大,也會越來越流行。下面結合MongoDB的幾大特色來談談MongoDB的適用場景。

首先,MongoDB是文件型(Document store)的NoSQL資料庫,資料以文件(對應關係型資料庫的記錄,本文有時候會混用)的形式在MongoDB中儲存,文件實際上就是一個個JSON字串,想必大家對JSON都比較熟悉,不贅述。使用JSON的好處是非常直觀,通過一系列的Key-Value鍵值對來表示資料,符合我們的閱讀習慣,下圖所示是以JSON表示的使用者資訊文件。

72ca6325-b60c-4dfb-808a-610ca8879e1c

在主流的計算機語言如Java、Python中對JSON都有很好的支援,資料從MongoDB中讀取出來後,可無需轉換直接使用;MongoDB文件另一個特點是Key-Value鍵值對支援豐富的資料結構,Value可以是普通的整型、字串,可以是陣列,也可以是巢狀的子文件,使用巢狀的好處是在MongoDB中僅需一次簡單的查詢就能夠獲取到你所需的資料。舉電商領域為例,網易嚴選上賣的上衣和褲子兩種商品,除了有共同屬性,如產地、價格、材質、顏色等外,還有各自有不同的屬性集,如上衣的獨有屬性是肩寬、胸圍、袖長等,褲子的獨有屬性是臀圍、腳口和褲長等。

57e47be0-5757-4e8d-93ca-31db13d830c5

這些獨有屬性可以直接以JSON子文件的方式巢狀在商品這個文件中,一次查詢直接獲取全部內容,不需要進行多表join;MongoDB文件的另一大特點是模式靈活:不同文件相同key的value型別可以是整形也可以是字串等其他型別,不同文件可以有不同的key,比如有些商品有折扣欄位,可以定義不同會員等級的不同折扣。在電商配套的物流領域,可以將一個快遞的物流資訊直接巢狀在以商品id為唯一索引的文件中,一次查詢就可以獲取完整的快遞流向資訊。MongoDB查詢還提供了非常豐富的操作符,在查詢中組合使用效率倍增。

基於文件的靈活的資料模式,是MongoDB的一大優勢,對於資料模型多樣或多變的業務場景,相比MySQL等資料庫,無需使用DDL語句進行表結構的修改;相比其他Key-Value資料庫,由於MongoDB的Value欄位對於MongoDB是非透明的,可以對其建立索引,還可以進行全文檢索,在查詢效率上更具優勢。該模式在遊戲、電商、社交、視訊直播、物流等領域非常適用,通過在使用者或商品中巢狀不同用途的子文件來實現快速查詢。對於監控、日誌資料儲存,第三方資訊抓取等場景也同樣適用,因為不同監控資料、日誌記錄、抓取的資料所包含的欄位往往是不一樣的,某種程度上說也是不可控的。同時,靈活的模式對於類似遊戲市場活動、移動App等要求快速開發上線但需求變動(導致資料模型變大)比較大的產品或場景也比較適用。

其次,MongoDB還具有強大的索引能力,支援建立唯一索引、二級索引、TTL索引和地理位置索引等,這在NoSQL資料庫中是數一數二的,在此基礎上,MongoDB還提供了執行計劃功能,通過explain()(https://docs.mongodb.com/manual/reference/method/db.collection.explain/#db.collection.explain)和hint()命令可以檢視執行計劃、強制查詢走某個索引,這些特性相比關係型資料庫也不成多讓。MongoDB集合在建立時預設就基於_id欄位建立了唯一索引,資料插入時會檢查_id欄位的唯一性,MongoDB可以在包括陣列中欄位或巢狀文件中的欄位幾乎任意欄位上建立索引(一般為二級索引),大大提高了查詢效率,在沒有跨記錄或跨表事務但對效能要求又非常高的某些場景下能夠替代關係型資料庫。在記憶體足夠的情況下,索引會被載入到Cache中,如果執行的查詢是索引覆蓋的(https://docs.mongodb.com/manual/core/query-optimization/#read-operations-covered-query),其效能甚至可以媲美Redis等記憶體資料庫等。TTL索引在儲存日誌或監控資料等場景下大有用武之地,通過建立TTL索引,實現自動刪除過期記錄的功能,(在使用MongoDB TTL索引需要注意,資料的過期時間無法精確控制,無法做到過期即刪除,在大資料量的情況下會有一定的效能開銷和刪除延遲)。

429da9c8-a207-4952-8670-f7472b1be7ff

地理位置索引是MongoDB早已被使用者所熟知的特性,其球面(Spherical)和平面(Flat)兩種模式,提供了豐富的地址位置的表示方式,如2d、2dsphere和GeoJSON等,對於移動App,如地圖軟體、打車軟體、外賣軟體,MongoDB強大的地理位置索引功能使其最佳選擇(https://www.mongodb.com/blog/post/geospatial-performance-improvements-in-mongodb-3-2);此外,對於物聯網、智慧都市等領域,也需要大量的地理位置相關操作,這些都是MongoDB的競技場。

再次,MongoDB的複製集是資料庫領域領先的高可用和讀寫負載均衡解決方案,提供了資料自動(非同步/同步)複製能力,一個新節點加入到複製集中會自動進行資料初始同步隨後使用oplog進行增量複製,無需人工干預;如果複製集的Primary節點發生宕機,MongoDB會自動進行主從切換,在複製集大多數節點線上的情況下,能夠基於Raft協議(MongoDB 3.2開始,之前版本不未使用Raft)自動地快速選出新的Primary並恢復讀寫服務(在選主期間,無法進行寫操作),無需人工干預;MongoDB運維人員所需做的僅僅是將宕機節點重新啟動,若宕機的是Primary,則重新啟動後,會自動進行資料回滾並最終成為複製集的Secondary節點(正常情況下)。

35c686b2-b6e9-4d7e-a468-30746c0f8e7d

在複製集機制下,還可以通過對節點進行滾動處理的方式進行線上維護升級。所以,相比目前的大多數關係型資料庫,MongoDB複製集實現了自動複製和故障切換,大大減低了運維複雜度,解放了DBA。如果你對資料的持久化和可用性有較高的要求,MongoDB複製集是上佳的選擇。此外,複製集還提供了Write Concern、Read Preference、Read Concern和Tag sets等讀寫行為控制功能,不同的業務應用型別可以參考官方手冊(https://docs.mongodb.com/manual/applications/replication/)根據對資料持久化、資料一致性和可用性的不同要求進行靈活地設定。

最後,MongoDB是為大資料而生的,提供sharding機制用於實現業務的水平擴充套件。每個shard都儲存業務的一部分資料,shard可以配置為複製集,確保shard上資料的高可用性,shard內部由一系列連續的chunk組成,chunk是某一片鍵區間內的資料記錄集合;mongos用於業務請求的路由,將業務負載分攤到不同的shard上,此外mongos還會對shard上超過一定大小的chunk進行分裂(split);根據不同shard中資料量的大小,在shard將進行chunk遷移(migrate),應該說sharding提供了完善的業務資料和負載水平擴充套件的機制,對於物聯網、日誌系統和監控系統這類包含TB級海量資料的應用場景,使用MongoDB sharding是個不錯的選擇。

63fa1f14-8303-40c2-85af-219e31e205c7

在生產環境中,sharding並不是必須的,並不是新業務起來的時候就馬上部署sharding叢集,只有當業務的資料量達到單個複製集無法支撐、或者業務的負載超過了複製集的服務能力的時候,才考慮部署sharding,畢竟相比複製集,sharding在部署和管理上都複雜很多。MongoDB複製集可以平滑升級到shard,所以當你真正需要sharding時,可以參考官方文件(https://docs.mongodb.com/manual/tutorial/convert-replica-set-to-replicated-shard-cluster/)進行操作,文件中提供了詳細的升級步驟。

介紹了MongoDB的優勢,也不得不提MongoDB的不足,MongoDB僅支援文件內的事務,所以對於需要跨文件或跨集合事務的應用,請謹慎使用MongoDB;另外,對於需要多表複雜Join的業務,還是使用關係型資料庫為好,MongoDB還在改善的路上;最後,對於PB級大資料量,且需要進行大規模計算的場景,使用MongoDB時需要配套使用Spark、Hadoop等大資料套件,讓MongoDB做正確的事情。總結起來,如果你的業務滿足一個或多個特點,那麼選擇MongoDB是個正確的決定:

    • 無需要跨文件或跨表的事務及複雜的join查詢支援

    • 敏捷迭代的業務,需求變動頻繁,資料模型無法確定

    • 儲存的資料格式靈活,不固定,或屬於半結構化資料

    • 業務併發訪問量大,需數千的QPS

    • TB級以上的海量資料儲存,且資料量不斷增加

    • 要求儲存的資料持久化、不丟失

    • 需要99.999%的資料高可用性

    • 需要大量的地理位置查詢、文字查詢

        目前開源資料庫眾多,大家可選的餘地很大,就會出現這樣的問題:MySQL、MongoDB、Redis、Hbase等這些資料庫哪個更好?其實這是一個偽命題,脫離了具體的業務場景來討論好壞是紙上談兵,沒有最好的,只有最合適的,誰也無法保證完全取代誰,上面的每種資料庫都在變得更好,都在不停地完善自身。比如MySQL在不斷提升其JSON和地理位置處理能力、組複製(group replication)已在開發等;而MongoDB在增強join型別支援,提供更為複雜的多集合查詢能力,計劃支援事務等;Redis也加入了地理位置處理能力。

        最後,以新鮮出爐的12月份最新DB-Engines排行榜來結束本篇文章:

cb62a2fb-7556-4301-94aa-8b2b75e7538b

免費體驗網易雲MongoDB服務,為開發者提供了一站式的 MongoDB 雲端解決方案,包括提供三節點複製集的高可用架構,故障切換,並提供專業的備份、監控以及效能優化方案,徹底免除開發者的運維煩惱。

本文來自網易雲社群 ,經作者溫正湖授權釋出。

網易雲免費體驗館,0成本體驗20+款雲產品!

更多網易研發、產品、運營經驗分享請訪問網易雲社群