- MongoDB進(jìn)階與實(shí)戰(zhàn):微服務(wù)整合、性能優(yōu)化、架構(gòu)管理
- 唐卓章
- 3031字
- 2021-05-19 17:44:34
第1部分 MongoDB入門(mén)
第1章 什么是MongoDB
1.1 認(rèn)識(shí)MongoDB
MongoDB是NoSQL數(shù)據(jù)庫(kù)中的佼佼者,目前是排名第一的文檔型數(shù)據(jù)庫(kù)。該數(shù)據(jù)庫(kù)基于靈活的JSON文檔模型,非常適合敏捷式的快速開(kāi)發(fā)。與此同時(shí),其與生俱來(lái)的高可用、高水平擴(kuò)展能力使得它在處理海量、高并發(fā)的數(shù)據(jù)應(yīng)用時(shí)頗具優(yōu)勢(shì)。
1.1.1 面向文檔設(shè)計(jì)
在我們的系統(tǒng)中,通常會(huì)用分層來(lái)描述現(xiàn)實(shí)中的模型,如圖1-1所示。

圖1-1 數(shù)據(jù)的分層模型
從下往上看,每一層都提供了更簡(jiǎn)單、更容易表述的模型來(lái)隱藏下層的復(fù)雜性。最為典型的是,數(shù)據(jù)庫(kù)系統(tǒng)屏蔽了所有磁盤(pán)中文件如何存取、壓縮/解壓縮等細(xì)節(jié),向應(yīng)用程序展示了一些通用的數(shù)據(jù)模型,如SQL表、列,或是基于JSON、XML的文檔模型。而應(yīng)用程序方面,面向?qū)ο蟮哪P鸵惨呀?jīng)被絕大多數(shù)人所熟知并接受。
在處理SQL數(shù)據(jù)模型時(shí),應(yīng)用程序需要通過(guò)代碼做一些必要的轉(zhuǎn)換工作,一般可以借助一些ORM框架來(lái)減少工作量,例如Hibernate。然而,SQL模型與面向?qū)ο笾g仍然存在不少差異,這些差異并不能完全通過(guò)框架屏蔽。相較之下,基于JSON的文檔模型則更能契合面向?qū)ο蟮脑O(shè)計(jì)準(zhǔn)則,對(duì)于開(kāi)發(fā)者來(lái)說(shuō),這在一定程度上降低了使用數(shù)據(jù)的門(mén)檻。
MongoDB是基于JSON來(lái)描述數(shù)據(jù)的,所有的“數(shù)據(jù)行”都可以通過(guò)一個(gè)JSON格式的文檔(document)來(lái)表示。比如下面的例子:

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

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

由此可見(jiàn),該數(shù)據(jù)庫(kù)的使用前景是非常廣闊的,隨著新版本中一些重要功能的補(bǔ)齊(比如事務(wù)),它所適用的場(chǎng)景將越來(lái)越多。
1.1.4 需要克服的困難
正如前面所說(shuō),MongoDB非常容易使用,但一些企業(yè)在初次選擇MongoDB之后可能會(huì)存在“水土不服”的問(wèn)題,具體如下。
1.關(guān)系型數(shù)據(jù)庫(kù)思維的轉(zhuǎn)變
如果團(tuán)隊(duì)長(zhǎng)期使用關(guān)系型數(shù)據(jù)庫(kù),那么團(tuán)隊(duì)成員可能已經(jīng)習(xí)慣于使用各種復(fù)雜連接(join)、多重嵌套子查詢等SQL用法。MongoDB在這方面的支持較弱,盡管可以通過(guò)聚合操作實(shí)現(xiàn)類(lèi)似的效果,但這并非最佳實(shí)踐。
在從關(guān)系型數(shù)據(jù)庫(kù)遷移到MongoDB之后,你需要從思維上產(chǎn)生一些轉(zhuǎn)變。盡可能讓數(shù)據(jù)庫(kù)設(shè)計(jì)變得簡(jiǎn)單、適用,將關(guān)注點(diǎn)放在系統(tǒng)未來(lái)的擴(kuò)展能力上,做好表設(shè)計(jì)、訪問(wèn)模式及性能的權(quán)衡。
2.事務(wù)方面的考量
在MongoDB 4.0版本之后,開(kāi)始支持事務(wù)功能,這意味著在一些對(duì)一致性要求非常高的場(chǎng)景中(比如金融交易類(lèi)產(chǎn)品)也可以使用MongoDB了。利用數(shù)據(jù)庫(kù)本身的事務(wù)性保證,還可以實(shí)現(xiàn)分布式事務(wù),這對(duì)于提升系統(tǒng)的可伸縮性有明顯的效果。
- Vue.js 3.x快速入門(mén)
- 高手是如何做產(chǎn)品設(shè)計(jì)的(全2冊(cè))
- Boost程序庫(kù)完全開(kāi)發(fā)指南:深入C++”準(zhǔn)”標(biāo)準(zhǔn)庫(kù)(第5版)
- Spring 5企業(yè)級(jí)開(kāi)發(fā)實(shí)戰(zhàn)
- JavaScript+DHTML語(yǔ)法與范例詳解詞典
- Oracle Database In-Memory(架構(gòu)與實(shí)踐)
- 區(qū)塊鏈架構(gòu)與實(shí)現(xiàn):Cosmos詳解
- 程序員考試案例梳理、真題透解與強(qiáng)化訓(xùn)練
- Python程序設(shè)計(jì)
- Mathematica Data Analysis
- MongoDB,Express,Angular,and Node.js Fundamentals
- NetBeans IDE 8 Cookbook
- CoffeeScript Application Development Cookbook
- ServiceNow:Building Powerful Workflows
- iPhone應(yīng)用開(kāi)發(fā)從入門(mén)到精通