主流NoSQL數據庫全方位評測之MongoDB
本篇要評測的NoSQL產品是MongoDB,它是現在開源社區里越來越受到關注的一個NoSQL產品,按照官方的說法,是一個可擴展的、高性能的、開源的、面向文檔的數據庫。Craigslist、foursquare、國內的淘寶網等知名互聯網公司都有在他們的生產環境部署了MongoDB。
一、MongoDB簡介
mongodb是用C++開發的面向文檔的數據庫,也就是反傳統的數據庫范式來設計的,把相關的對象都記錄到一個文檔里,每個文檔內是schema-free的,也就是列名可以自由定義,比較靈活,特別是面對業務邏輯多變的應用場景十分給力。數據以BSON(類似JSON)的格式二進制存儲。不好的地方就是可能帶來一定的數據冗余和存儲開銷。
很明顯,MongoDB這種面向文檔的數據庫和傳統的關系型數據庫的設計思路是差別很大的,因為每個文檔都包含了所有信息,和其他文檔是沒有關聯的,這樣傳統的Join操作就完全沒必要了,也正是因為去除了這種“關系”,使得MongoDB的水平拆分更加容易,這也是面對海量數據的一個很好的處理思路。另外,MongoDB的索引機制和MySQL等數據庫是一樣的,可以利用傳統的關系型數據庫的經驗來使用MongoDB的索引。
不像其他很多NoSQL產品由個別工程師根據應用場景開發出來,MongoDB是有一個專門的公司10gen來維護。有一點要注意的是,MongoDB自己是不管理內存的,無法指定內存大小,完全交給操作系統來管理,因此有時候是不可控的,在生產環境使用必須在OS層面監控內存使用情況。
二、測試說明
1、測試環境
MongoDB部署在一臺PC 服務器上,配置如下:
CPU為Xeon 2.80GHz *4
內存為4G
硬盤為一塊400G SATA盤
操作系統為64位CentOS 5.3版本
2、測試方法
這里仍然采用PHP客戶端進行測試,MongoDB官方為PHP開發了一個擴展包可以操作MongoDB,網址為http://pecl.php.net/package/mongo,可以編譯到PHP運行環境中來使用。
為了不對測試服務器產生額外的影響,測試客戶端部署在另外一臺獨立的服務器上,運行的PHP的版本是5.3.5,web server是Nginx 0.8.54,通過fastcgi的方式調用PHP服務。使用apache ab工具實現多個請求和并發操作。
測試過程中就使用上文提到的已經啟動的數據庫實例,首先是進行寫操作,通過500個請求,每個請求寫入10000條記錄,并發度為2來共寫入500萬條數據,MongoDB的數據格式是BSON方式,不同于其他的NoSQL是key value的方式,因此這里寫入的數據格式為:{id,data}的形式,ID為數字1到5000000,data大小為100個字節。然后是讀操作,也是用500個請求,每個請求隨機根據ID值讀出10000條記錄,并發度為10共讀出500萬條記錄,評測的重點是寫入和讀出數據的時間,以及在此過程中服務器的資源使用情況。
需要說明的是,MongoDB默認會為每個記錄建立一個名字為_id的索引,在沒有索引的情況下MongoDB讀數據都要進行全表掃描,效率還是很低的,因此在寫完500萬條記錄后,我在id字段上建立了一個索引來加快讀的過程。
三、安裝和使用
mongodb目前最新的版本是.8.2-rc3,其源碼安裝用了很多第三方的東西,比如JS引擎(目前官方推薦的是mozilla的Spider Monkey,以后可能改成google的V8,和node.js一樣,呵呵)、正則表達式引擎(pcre)、安裝構建工具scons(這東西還要用python來安裝)、boost C++庫等等。下面是安裝過程:
1、下載需要的源文件和相關軟件包:
- [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端口監聽,而28017端口是web管理的端口,可通過http方式來訪問。為了規范,我們用以下命令啟動一個mongod進程:
- [root@localhost data]# /usr/local/mongodb/bin/mongod --fork --dbpath /home/mongo/data/ --logpath /home/mongo/mongo.log --logappend --directoryperdb --journal --rest
這樣一個mongod進程就啟動了,它監聽27017端口來提供服務,可以在應用程序中進行建立數據庫等操作,它不像傳統的Oracle等關系數據庫那樣,建庫是個很慎重的工作。要了解更詳細的使用MongoDB的信息,讀者可以參看官方文檔,這里就不提及了。
四、測試結果
1、寫操作
成功寫入416萬條記錄,寫入失敗84萬條記錄,共耗時525秒,平均每秒寫入數據7924筆。數據文件大小近4G。寫入過程中,服務器內存、CPU和磁盤等資源使用情況如下圖所示:
可見,內存使用呈階梯狀上升,最后占用了近3.5個G,主要用來緩存數據,對比數據文件的大小可以設想,在操作系統內存可用的情況下,內存的分配和數據文件的大小是大致相當的。CPU和磁盤IO都表現出周期性的上下波動,估計和操作系統mmap緩存數據和刷新到磁盤的實現機制有關。從圖表可見本次測試的瓶頸同樣出現在磁盤IO上,磁盤的使用率最后達到100%,導致無法成功寫入數據。
2、讀操作
成功讀出500萬條記錄,共耗時432秒,平均每秒讀出數據11574筆。
讀數據過程中沒有發生磁盤IO。CPU較繁忙,Idle值穩定在27左右,等待CPU資源的進程一直在5到10個之間。內存表現平穩沒有波動。
五、總結
通過以上測試結果可以看出,MongoDB占用的磁盤空間很大,這是因為其占用的磁盤空間是預分配的,每次以上一個數據文件的兩倍大小來預分配空間,并以0來填充,以避免在繁忙時期分配磁盤空間導致性能下降,因此我們看到的數據文件大小并不是實際占用的空間大小。另外其內存是由操作系統管理的,自身并不管理內存使用。從功能角度看MongoDB提供的查詢等操作接口是最為豐富的,在面對海量數據的拆分等可擴展方面也有很好的設計思路,是一個很好的將數據模型從面向關系轉向面向文檔的NoSQL產品,相信將來會看到更多的線上產品選用MongoDB。
【編輯推薦】