- MongoDB進階與實戰:微服務整合、性能優化、架構管理
- 唐卓章
- 7字
- 2021-05-19 17:44:34
第1部分 MongoDB入門
第1章 什么是MongoDB
1.1 認識MongoDB
MongoDB是NoSQL數據庫中的佼佼者,目前是排名第一的文檔型數據庫。該數據庫基于靈活的JSON文檔模型,非常適合敏捷式的快速開發。與此同時,其與生俱來的高可用、高水平擴展能力使得它在處理海量、高并發的數據應用時頗具優勢。
1.1.1 面向文檔設計
在我們的系統中,通常會用分層來描述現實中的模型,如圖1-1所示。

圖1-1 數據的分層模型
從下往上看,每一層都提供了更簡單、更容易表述的模型來隱藏下層的復雜性。最為典型的是,數據庫系統屏蔽了所有磁盤中文件如何存取、壓縮/解壓縮等細節,向應用程序展示了一些通用的數據模型,如SQL表、列,或是基于JSON、XML的文檔模型。而應用程序方面,面向對象的模型也已經被絕大多數人所熟知并接受。
在處理SQL數據模型時,應用程序需要通過代碼做一些必要的轉換工作,一般可以借助一些ORM框架來減少工作量,例如Hibernate。然而,SQL模型與面向對象之間仍然存在不少差異,這些差異并不能完全通過框架屏蔽。相較之下,基于JSON的文檔模型則更能契合面向對象的設計準則,對于開發者來說,這在一定程度上降低了使用數據的門檻。
MongoDB是基于JSON來描述數據的,所有的“數據行”都可以通過一個JSON格式的文檔(document)來表示。比如下面的例子:

很明顯,基于JSON格式的數據模型可讀性非常強,也更加靈活;除了基本的數據類型,文檔中還可以使用數組、內嵌子對象等高級的字段類型。
此外,JSON還具備無模式(模式靈活)的特點,可以輕松地進行擴展。在訪問MongoDB的“表”之前,并不需要事先對表模型進行聲明(盡管你也可以這么做)。同時,當數據模型發生變更時,MongoDB不會強制要求你去執行表結構更新的相關操作,這提供了很大的便利性。
在MongoDB內部,BSON(一種二進制版本的JSON擴展)被真正用來存儲這些JSON形式的文檔數據。在JSON的基礎之上,BSON進行了一些易用性方面的擴展,例如增加日期、二進制等類型的支持。
雖然MongoDB“沿襲”了JSON的特點,但將它歸類為無模式數據庫是不恰當的。實際上,所有的讀寫都是基于一種內部隱含的模式,模式采取按需變更而非提前聲明,因此動態模式一詞更適合它。
1.1.2 特性
1.完備的索引
與大多數數據庫一樣,MongoDB支持各種豐富的索引類型,包括單鍵索引、復合索引,唯一索引等一些常用的結構。由于采用了靈活可變的文檔類型,因此它也同樣支持對嵌套字段、數組進行索引。通過建立合適的索引,我們可以極大地提升數據的檢索速度。值得一提的是,MongoDB的索引實現與一般的關系型數據庫索引并沒有太多不同,因此,我們幾乎可以使用某種“一致的思路”來設計索引或完成一些性能調優的任務。
在一些特殊應用場景,MongoDB還支持地理空間索引、文本檢索索引、TTL索引等不同的特性,這些特性在很大程度上簡化了應用程序的開發工作,同時也使MongoDB獲得了大量使用者的青睞。
2.跨平臺,支持各種編程語言
MongoDB是用C++語言編寫的,其官方網站提供了各種平臺的編譯版本,你可以在Windows或幾乎任意一個Linux發行版本中安裝及運行MongoDB數據庫。
以X86_64體系為例,MongoDB支持的操作系統如圖1-2所示。

圖1-2 MongoDB支持的操作系統
需要注意的是,在MongoDB 3.4以后,不再支持32-bit X86體系,但這點的影響很小,作為一款通用的后端數據庫來說,使用64位的計算架構是必然的選擇。
在客戶端方面,MongoDB提供了多種編程語言實現的驅動程序,除了Java、C/C++/C#等傳統語言,像Python、NodeJS等動態語言也都有對應的實現。
3.強大的聚合計算
聚合(aggregation)計算是MongoDB面向數據分析領域的重要特性,可以用于實現數據的分類統計或一些管道計算。
作為對照,聚合框架能輕松完成關系型數據庫的group by語句的分組功能,又或是大數據領域的map-reduce計算。
可能存在的一點區別就是,MongoDB聚合框架是以文檔化模型為基礎來設計的,更適合非結構化數據。
MongoDB為聚合框架提供了大量常用的函數以簡化開發,除此之外,聚合框架還用到了一種叫“管道”(pipeline)的概念,用于抽象各個數據處理的階段,一個管道由多個“階段”(stage)組成,通過對不同的階段進行自由組合,我們就可以靈活應對各種場景中的計算需求。
4.復制、分布式
MongoDB通過副本集(replication set)來實現數據庫的高可用,這點類似于MySQL的Master/Slave復制架構,不同的是,一個副本集可以由一個主節點和多個備節點組成,主節點和備節點基于oplog來實現數據同步。在主節點發生故障時,備節點將重新選舉出新的主節點以繼續提供服務,整個切換過程是自動完成的。
在海量數據處理方面,MongoDB原生就支持分布式計算能力。在一個分布式集群中,多個文檔被劃入一個邏輯數據塊(chunk),這些數據塊可以被存儲于不同的計算節點(分片)上,在新的計算節點(分片)加入時,數據塊可以借助自動均衡的算法機制被遷移到合適的位置(通常是壓力較小的分片)。通過這種自動化的調度及均衡工作,整個集群的數據庫讀寫壓力可以被分攤到多個節點上,從而實現負載均衡和水平擴展。
1.1.3 優勢
在選擇某個數據庫時,通常都會從各個方面進行考量。對于MongoDB來說,筆者認為,它的優勢主要有以下幾點。
1.易用性
筆者認為,簡單易用是MongoDB的一大優勢。MongoDB是基于JSON格式的,這點對于開發人員來說顯然更加友好,尤其是對全棧式開發者來說,JSON是前后端開發領域中最通用、易讀的描述性語言。
如果你是一名新手,則只需要了解一點JavaScript的語法就可以基本掌握一種數據庫的使用,這聽起來非常振奮人心。
另外一點,則是無模式帶來的便利,由于沒有了強制的表定義約束,在文檔結構發生變化時并不需要如關系型數據庫一樣事先執行一些DDL變更語句,這非常有利于業務的平滑升級。因此,MongoDB的開發效率更高,更適合敏捷開發。
2.高性能
從MongoDB 3.0版本開始引入WiredTiger存儲引擎,在性能及穩定性上都有了明顯的提升。
WiredTiger存儲引擎在數據檢索性能上做了許多優化,基于內存的二級的緩存提供了高速讀取數據能力,在寫方面則是根據磁盤I/O的特點做了緩沖式寫入,這是基于空間、時間因素權衡的一種擇優設計。從大量的測評結果來看,其性能表現是令人滿意的。
3.高可靠
對于單個MongoDB節點來說,可以通過開啟Journal機制來實現斷電保護,這是一種WAL預寫日志機制,在發生異常斷電后,可以通過Journal日志進行數據恢復。在默認情況下,Journal僅允許最多丟失50ms內更新的數據。
對于集群節點來說,MongoDB則提供了副本集架構來支持數據庫的高可用,在節點發生宕機時,可以實現秒級的切換,這個過程對于應用是透明的。
4.高可擴展
在分片的集群架構中,數據的讀寫會均衡地分布在多個數據庫節點上,通過增加分片的方式就可以實現按需擴展。在數據業務持續增長時,借助分片集群可以輕松支撐海量的數據存取。
5.強大的社區支持
MongoDB有著龐大的使用群體,在一定程度上鞏固了它在NoSQL領域的領先地位。
也因為該數據庫是如此流行,國內外各大云計算廠商基本都提供了MongoDB協議兼容的數據庫服務,見表1-1。
表1-1 各云廠商支持的類MongoDB產品

由此可見,該數據庫的使用前景是非常廣闊的,隨著新版本中一些重要功能的補齊(比如事務),它所適用的場景將越來越多。
1.1.4 需要克服的困難
正如前面所說,MongoDB非常容易使用,但一些企業在初次選擇MongoDB之后可能會存在“水土不服”的問題,具體如下。
1.關系型數據庫思維的轉變
如果團隊長期使用關系型數據庫,那么團隊成員可能已經習慣于使用各種復雜連接(join)、多重嵌套子查詢等SQL用法。MongoDB在這方面的支持較弱,盡管可以通過聚合操作實現類似的效果,但這并非最佳實踐。
在從關系型數據庫遷移到MongoDB之后,你需要從思維上產生一些轉變。盡可能讓數據庫設計變得簡單、適用,將關注點放在系統未來的擴展能力上,做好表設計、訪問模式及性能的權衡。
2.事務方面的考量
在MongoDB 4.0版本之后,開始支持事務功能,這意味著在一些對一致性要求非常高的場景中(比如金融交易類產品)也可以使用MongoDB了。利用數據庫本身的事務性保證,還可以實現分布式事務,這對于提升系統的可伸縮性有明顯的效果。
- iOS面試一戰到底
- Hands-On Machine Learning with scikit:learn and Scientific Python Toolkits
- Ceph Cookbook
- Python從菜鳥到高手(第2版)
- JavaScript從入門到精通(第3版)
- Python數據挖掘與機器學習實戰
- Advanced Oracle PL/SQL Developer's Guide(Second Edition)
- Go并發編程實戰
- Mathematica Data Analysis
- Visual C#通用范例開發金典
- Bootstrap 4 Cookbook
- UI設計全書(全彩)
- 代碼閱讀
- Angular Design Patterns
- Access數據庫應用教程(2010版)