主流NoSQL數(shù)據(jù)庫全方位評測之MongoDB
本篇要評測的NoSQL產(chǎn)品是MongoDB,它是現(xiàn)在開源社區(qū)里越來越受到關(guān)注的一個NoSQL產(chǎn)品,按照官方的說法,是一個可擴展的、高性能的、開源的、面向文檔的數(shù)據(jù)庫。Craigslist、foursquare、國內(nèi)的淘寶網(wǎng)等知名互聯(lián)網(wǎng)公司都有在他們的生產(chǎn)環(huán)境部署了MongoDB。
一、MongoDB簡介
mongodb是用C++開發(fā)的面向文檔的數(shù)據(jù)庫,也就是反傳統(tǒng)的數(shù)據(jù)庫范式來設(shè)計的,把相關(guān)的對象都記錄到一個文檔里,每個文檔內(nèi)是schema-free的,也就是列名可以自由定義,比較靈活,特別是面對業(yè)務(wù)邏輯多變的應(yīng)用場景十分給力。數(shù)據(jù)以BSON(類似JSON)的格式二進制存儲。不好的地方就是可能帶來一定的數(shù)據(jù)冗余和存儲開銷。
很明顯,MongoDB這種面向文檔的數(shù)據(jù)庫和傳統(tǒng)的關(guān)系型數(shù)據(jù)庫的設(shè)計思路是差別很大的,因為每個文檔都包含了所有信息,和其他文檔是沒有關(guān)聯(lián)的,這樣傳統(tǒng)的Join操作就完全沒必要了,也正是因為去除了這種“關(guān)系”,使得MongoDB的水平拆分更加容易,這也是面對海量數(shù)據(jù)的一個很好的處理思路。另外,MongoDB的索引機制和MySQL等數(shù)據(jù)庫是一樣的,可以利用傳統(tǒng)的關(guān)系型數(shù)據(jù)庫的經(jīng)驗來使用MongoDB的索引。
不像其他很多NoSQL產(chǎn)品由個別工程師根據(jù)應(yīng)用場景開發(fā)出來,MongoDB是有一個專門的公司10gen來維護。有一點要注意的是,MongoDB自己是不管理內(nèi)存的,無法指定內(nèi)存大小,完全交給操作系統(tǒng)來管理,因此有時候是不可控的,在生產(chǎn)環(huán)境使用必須在OS層面監(jiān)控內(nèi)存使用情況。
二、測試說明
1、測試環(huán)境
MongoDB部署在一臺PC 服務(wù)器上,配置如下:
CPU為Xeon 2.80GHz *4
內(nèi)存為4G
硬盤為一塊400G SATA盤
操作系統(tǒng)為64位CentOS 5.3版本
2、測試方法
這里仍然采用PHP客戶端進行測試,MongoDB官方為PHP開發(fā)了一個擴展包可以操作MongoDB,網(wǎng)址為http://pecl.php.net/package/mongo,可以編譯到PHP運行環(huán)境中來使用。
為了不對測試服務(wù)器產(chǎn)生額外的影響,測試客戶端部署在另外一臺獨立的服務(wù)器上,運行的PHP的版本是5.3.5,web server是Nginx 0.8.54,通過fastcgi的方式調(diào)用PHP服務(wù)。使用apache ab工具實現(xiàn)多個請求和并發(fā)操作。
測試過程中就使用上文提到的已經(jīng)啟動的數(shù)據(jù)庫實例,首先是進行寫操作,通過500個請求,每個請求寫入10000條記錄,并發(fā)度為2來共寫入500萬條數(shù)據(jù),MongoDB的數(shù)據(jù)格式是BSON方式,不同于其他的NoSQL是key value的方式,因此這里寫入的數(shù)據(jù)格式為:{id,data}的形式,ID為數(shù)字1到5000000,data大小為100個字節(jié)。然后是讀操作,也是用500個請求,每個請求隨機根據(jù)ID值讀出10000條記錄,并發(fā)度為10共讀出500萬條記錄,評測的重點是寫入和讀出數(shù)據(jù)的時間,以及在此過程中服務(wù)器的資源使用情況。
需要說明的是,MongoDB默認會為每個記錄建立一個名字為_id的索引,在沒有索引的情況下MongoDB讀數(shù)據(jù)都要進行全表掃描,效率還是很低的,因此在寫完500萬條記錄后,我在id字段上建立了一個索引來加快讀的過程。
三、安裝和使用
mongodb目前最新的版本是.8.2-rc3,其源碼安裝用了很多第三方的東西,比如JS引擎(目前官方推薦的是mozilla的Spider Monkey,以后可能改成google的V8,和node.js一樣,呵呵)、正則表達式引擎(pcre)、安裝構(gòu)建工具scons(這東西還要用python來安裝)、boost C++庫等等。下面是安裝過程:
1、下載需要的源文件和相關(guān)軟件包:
- [root@localhost mongodb]# wget http://downloads.mongodb.org/src/mongodb-src-r1.8.2-rc3.tar.gz
- [root@localhost mongodb]# wget http://sourceforge.net/projects/scons/files/scons/2.1.0.alpha.20101125/scons-2.1.0.alpha.20101125.tar.gz/download
- [root@localhost mongodb]# wget http://ftp.mozilla.org/pub/mozilla.org/js/js-1.7.0.tar.gz
- [root@localhost mongodb]# wget http://sourceforge.net/projects/pcre/files/pcre/7.4/pcre-7.4.tar.gz/download
2、安裝scons:
- [root@localhost mongodb]# tar zxvf scons-2.1.0.alpha.20101125.tar.gz
- [root@localhost mongodb]# cd scons-2.1.0.alpha.20101125
- [root@localhost scons-2.1.0.alpha.20101125]# python setup.py install
3、安裝pcre:
- [root@localhost mongodb]# tar zxvf pcre-7.4.tar.gz
- [root@localhost mongodb]# cd pcre-7.4
- [root@localhost pcre-7.4]# ./configure
- [root@localhost pcre-7.4]# make
- [root@localhost pcre-7.4]# make install
4、安裝Spider Monkey:
- [root@localhost mongodb]# tar zxvf js-1.7.0.tar.gz
- [root@localhost mongodb]# cd js/src
- [root@localhost src]# export CFLAGS="-DJS_C_STRINGS_ARE_UTF8"
- [root@localhost src]# make -f Makefile.ref
- [root@localhost src]# JS_DIST=/usr make -f Makefile.ref export
5、安裝boost,yum方式比較偷懶:
- [root@localhost src]# yum -y install boost boost-devel
6、安裝mongodb:
- [root@localhost mongodb]# tar zxvf mongodb-src-r1.8.2-rc3.tar.gz
- [root@localhost mongodb]# cd mongodb-src-r1.8.2-rc3
- [root@localhost mongodb-src-r1.8.2-rc3]# scons all
- [root@localhost mongodb-src-r1.8.2-rc3]# scons --prefix=/usr/local/mongodb --full install
這樣就安裝完畢了,可以簡單的啟動mongod進程來驗證一下:
- [root@localhost bin]# ./mongod --dbpath /tmp
- Wed Jun 8 11:57:38 [initandlisten] MongoDB starting : pid=29700 port=27017 dbpath=/tmp 64-bit
- Wed Jun 8 11:57:38 [initandlisten] db version v1.8.2-rc3, pdfile version 4.5
- Wed Jun 8 11:57:38 [initandlisten] git version: nogitversion
- Wed Jun 8 11:57:38 [initandlisten] build sys info: Linux localhost.localdomain 2.6.18-128.el5 #1 SMP Wed Jan 21 10:41:14 EST 2009 x86_64 BOOST_LIB_VERSION=1_33_1
- Wed Jun 8 11:57:38 [initandlisten] waiting for connections on port 27017
- Wed Jun 8 11:57:38 [websvr] web admin interface listening on port 28017
可見mongod默認在27017端口監(jiān)聽,而28017端口是web管理的端口,可通過http方式來訪問。為了規(guī)范,我們用以下命令啟動一個mongod進程:
- [root@localhost data]# /usr/local/mongodb/bin/mongod --fork --dbpath /home/mongo/data/ --logpath /home/mongo/mongo.log --logappend --directoryperdb --journal --rest
這樣一個mongod進程就啟動了,它監(jiān)聽27017端口來提供服務(wù),可以在應(yīng)用程序中進行建立數(shù)據(jù)庫等操作,它不像傳統(tǒng)的Oracle等關(guān)系數(shù)據(jù)庫那樣,建庫是個很慎重的工作。要了解更詳細的使用MongoDB的信息,讀者可以參看官方文檔,這里就不提及了。
四、測試結(jié)果
1、寫操作
成功寫入416萬條記錄,寫入失敗84萬條記錄,共耗時525秒,平均每秒寫入數(shù)據(jù)7924筆。數(shù)據(jù)文件大小近4G。寫入過程中,服務(wù)器內(nèi)存、CPU和磁盤等資源使用情況如下圖所示:
可見,內(nèi)存使用呈階梯狀上升,最后占用了近3.5個G,主要用來緩存數(shù)據(jù),對比數(shù)據(jù)文件的大小可以設(shè)想,在操作系統(tǒng)內(nèi)存可用的情況下,內(nèi)存的分配和數(shù)據(jù)文件的大小是大致相當?shù)?。CPU和磁盤IO都表現(xiàn)出周期性的上下波動,估計和操作系統(tǒng)mmap緩存數(shù)據(jù)和刷新到磁盤的實現(xiàn)機制有關(guān)。從圖表可見本次測試的瓶頸同樣出現(xiàn)在磁盤IO上,磁盤的使用率最后達到100%,導(dǎo)致無法成功寫入數(shù)據(jù)。
2、讀操作
成功讀出500萬條記錄,共耗時432秒,平均每秒讀出數(shù)據(jù)11574筆。
讀數(shù)據(jù)過程中沒有發(fā)生磁盤IO。CPU較繁忙,Idle值穩(wěn)定在27左右,等待CPU資源的進程一直在5到10個之間。內(nèi)存表現(xiàn)平穩(wěn)沒有波動。
五、總結(jié)
通過以上測試結(jié)果可以看出,MongoDB占用的磁盤空間很大,這是因為其占用的磁盤空間是預(yù)分配的,每次以上一個數(shù)據(jù)文件的兩倍大小來預(yù)分配空間,并以0來填充,以避免在繁忙時期分配磁盤空間導(dǎo)致性能下降,因此我們看到的數(shù)據(jù)文件大小并不是實際占用的空間大小。另外其內(nèi)存是由操作系統(tǒng)管理的,自身并不管理內(nèi)存使用。從功能角度看MongoDB提供的查詢等操作接口是最為豐富的,在面對海量數(shù)據(jù)的拆分等可擴展方面也有很好的設(shè)計思路,是一個很好的將數(shù)據(jù)模型從面向關(guān)系轉(zhuǎn)向面向文檔的NoSQL產(chǎn)品,相信將來會看到更多的線上產(chǎn)品選用MongoDB。
【編輯推薦】




























