MongoDB的正確使用姿勢

kvsh8744 8年前發布 | 36K 次閱讀 MongoDB NoSQL數據庫

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

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

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

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

其次,MongoDB還具有強大的索引能力,支持創建唯一索引、二級索引、TTL索引和地理位置索引等,這在NoSQL數據庫中是數一數二的,在此基礎上,MongoDB還提供了執行計劃功能,通過explain()和hint()命令可以查看執行計劃、強制查詢走某個索引,這些特性相比關系型數據庫也不成多讓。MongoDB集合在創建時默認就基于_id字段創建了唯一索引,數據插入時會檢查_id字段的唯一性,MongoDB可以在包括數組中字段或嵌套文檔中的字段幾乎任意字段上創建索引(一般為二級索引),大大提高了查詢效率,在沒有跨記錄或跨表事務但對性能要求又非常高的某些場景下能夠替代關系型數據庫。在內存足夠的情況下,索引會被加載到Cache中,如果執行的查詢是索引覆蓋的,其性能甚至可以媲美Redis等內存數據庫等。TTL索引在保存日志或監控數據等場景下大有用武之地,通過創建TTL索引,實現自動刪除過期記錄的功能,(在使用MongoDB TTL索引需要注意,數據的過期時間無法精確控制,無法做到過期即刪除,在大數據量的情況下會有一定的性能開銷和刪除延遲)。

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

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

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

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

在生產環境中,sharding并不是必須的,并不是新業務起來的時候就馬上部署sharding集群,只有當業務的數據量達到單個復制集無法支撐、或者業務的負載超過了復制集的服務能力的時候,才考慮部署sharding,畢竟相比復制集,sharding在部署和管理上都復雜很多。

介紹了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也加入了地理位置處理能力。

 

來自:http://www.bitstech.net/2016/12/12/mongodb的正確使用姿勢/

 

 本文由用戶 kvsh8744 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!