白長(zhǎng)清++劉敏
摘 要:海量規(guī)模數(shù)據(jù)不斷涌現(xiàn),對(duì)非結(jié)構(gòu)型數(shù)據(jù)的存儲(chǔ)和處理需求日益增長(zhǎng),傳統(tǒng)的關(guān)系數(shù)據(jù)庫(kù)很難對(duì)其高效處理,NoSQL技術(shù)則能比較好的解決這類(lèi)問(wèn)題。本文將介紹NoSQL,MongoDB,以及MongoDB在處理海量氣象參數(shù)的傳感器數(shù)據(jù)時(shí)的應(yīng)用。實(shí)踐證明,以MongoDB為代表的NoSQL數(shù)據(jù)庫(kù)在存儲(chǔ)和訪(fǎng)問(wèn)海量的非結(jié)構(gòu)化數(shù)據(jù)時(shí),有著良好的性能。
關(guān)鍵詞:NoSQL;MongoDB;海量數(shù)據(jù);面向文檔
中圖分類(lèi)號(hào):TP311
文獻(xiàn)標(biāo)識(shí)碼:A
DOI: 10.3969/j.issn.1003-6970.2015.11.010
0 引言
隨著云計(jì)算時(shí)代的到來(lái),web2.0的快速發(fā)展,非關(guān)系型、分布式數(shù)據(jù)存儲(chǔ)得到了快速的發(fā)展,它們具有非常高的讀寫(xiě)性能,尤其在大數(shù)據(jù)量下。而且NoSQL具有靈活的數(shù)據(jù)模型,即無(wú)需事先為要存儲(chǔ)的數(shù)據(jù)建立字段,隨時(shí)可以存儲(chǔ)白定義的數(shù)據(jù)格式。在不太影響性能的情況下,就可以方便的實(shí)現(xiàn)高可用的架構(gòu)。面向文檔的MongoDB,其數(shù)據(jù)結(jié)構(gòu)非常松散,可以存儲(chǔ)比較復(fù)雜的數(shù)據(jù)類(lèi)型,保證海量數(shù)據(jù)存儲(chǔ)的同時(shí),具有良好的查詢(xún)性能,擁有廣泛應(yīng)用。
在本實(shí)驗(yàn)室氣象局項(xiàng)目中,需要存儲(chǔ)、查詢(xún)大量氣象參數(shù)測(cè)量傳感器數(shù)據(jù),每次測(cè)量的數(shù)據(jù)通道并不都是一致,即測(cè)量數(shù)據(jù)是弱一致性的,還要求保持可擴(kuò)展性,并且能夠便捷的獲取數(shù)據(jù),而MongoDB能很好的滿(mǎn)足這些需求,本文將以實(shí)驗(yàn)室氣象參數(shù)測(cè)量傳感器數(shù)據(jù)的處理為背景,介紹MongoDB在實(shí)際生產(chǎn)中的運(yùn)用。
1 NoSQL
1.1 概述
NoSQL是對(duì)非關(guān)系型數(shù)據(jù)庫(kù)系統(tǒng)的總稱(chēng),意思是No SQL(沒(méi)有SQL語(yǔ)言)。它與關(guān)系型數(shù)據(jù)庫(kù)最重要的不同是:NoSQL不使用SQL作為查詢(xún)語(yǔ)言。其數(shù)據(jù)存儲(chǔ)可以不需要固定的表格模式,也經(jīng)常會(huì)避免使用SQL的JOIN操作,一般具有水平可擴(kuò)展的特征。在大量數(shù)據(jù)存取上具備關(guān)系型數(shù)據(jù)庫(kù)無(wú)法比擬的性能優(yōu)勢(shì)。NoSQL數(shù)據(jù)庫(kù)憑借著其非關(guān)系型、分布式、開(kāi)源和橫向擴(kuò)展等優(yōu)勢(shì),被認(rèn)為是下一代數(shù)據(jù)庫(kù)產(chǎn)品。
1.2 NoSQL分類(lèi)
NoSQL可以大體上分為4個(gè)種類(lèi):Key-value(鍵值存儲(chǔ))、Document-Oriented(面向文檔)、Column-Family Databases(面向表列)以及Graph-Oriented Databases(面向圖論)。下面就一覽這些類(lèi)型的特性:
鍵值數(shù)據(jù)庫(kù):通過(guò)key快速查詢(xún)到其value,存儲(chǔ)并不關(guān)心值的格式,比如通過(guò)國(guó)際標(biāo)準(zhǔn)書(shū)號(hào)ISBN找一本書(shū),在這里,ISBN是鍵,書(shū)籍的其他信息就是值。必須知道鍵才能查詢(xún)。
文檔存儲(chǔ)數(shù)據(jù)庫(kù):面向文檔數(shù)據(jù)庫(kù)會(huì)將數(shù)據(jù)以文檔的形式儲(chǔ)存。每個(gè)文檔都是白包含的數(shù)據(jù)單元,是一系列數(shù)據(jù)項(xiàng)的集合。每個(gè)數(shù)據(jù)項(xiàng)都有一個(gè)名稱(chēng)與對(duì)應(yīng)的值,值既可以是簡(jiǎn)單的數(shù)據(jù)類(lèi)型,如字符串、數(shù)字和日期等;也可以是復(fù)雜的類(lèi)型,如有序列表和關(guān)聯(lián)對(duì)象。
列式數(shù)據(jù)庫(kù):也被稱(chēng)為列式存儲(chǔ)或?qū)捔写鎯?chǔ),對(duì)數(shù)據(jù)進(jìn)行列式存儲(chǔ)。最大的特點(diǎn)是方便存儲(chǔ)結(jié)構(gòu)化和半結(jié)構(gòu)化數(shù)據(jù),方便做數(shù)據(jù)壓縮,對(duì)針對(duì)某一列或者某幾列的查詢(xún)有非常大的10優(yōu)勢(shì)。
圖型數(shù)據(jù)庫(kù):圖型數(shù)據(jù)庫(kù)關(guān)注值與值之間的關(guān)系,用圖型的數(shù)學(xué)概念存儲(chǔ)數(shù)據(jù)。圖型數(shù)據(jù)庫(kù)用帶有點(diǎn)、邊緣和屬性的圖的結(jié)構(gòu)表示和存儲(chǔ)數(shù)據(jù)。在圖型數(shù)據(jù)庫(kù)中,每一個(gè)元素都包含一個(gè)直接的指向它毗鄰元素的點(diǎn),所以也就不需要索引查找。
1.3 優(yōu)缺點(diǎn)
NoSQL數(shù)據(jù)庫(kù)最大的優(yōu)點(diǎn)在于它的去中心化、可擴(kuò)展、容錯(cuò)能力等屬性。用NoSQL數(shù)據(jù)庫(kù),你可以為每一個(gè)特殊的用例定制化你的數(shù)據(jù)管理解決方案。另外,大多數(shù)NoSQL產(chǎn)品都是輕量級(jí)的,因此花費(fèi)比較少。自從NoSQL產(chǎn)品被設(shè)計(jì)用來(lái)滿(mǎn)足特殊的用例和解決特殊的問(wèn)題,它的功能也就比大多數(shù)關(guān)系型數(shù)據(jù)庫(kù)少,因?yàn)楹笳咭獞?yīng)用于更廣泛的領(lǐng)域。因此,NoSQL數(shù)據(jù)庫(kù)需要的代碼更少,這也是和復(fù)雜的關(guān)系型數(shù)據(jù)庫(kù)相比具備的一項(xiàng)優(yōu)勢(shì)。
當(dāng)然,NoSQL也有它的缺點(diǎn)。ACID協(xié)議是關(guān)系型數(shù)據(jù)庫(kù)的標(biāo)準(zhǔn),但很多NoSQL數(shù)據(jù)庫(kù)做不到。如果ACID支持很關(guān)鍵,你必須要確定你選的NoSQL數(shù)據(jù)庫(kù)是否提供ACID。NoSQL數(shù)據(jù)庫(kù)的另一個(gè)缺點(diǎn)是不支持SQL語(yǔ)言。經(jīng)過(guò)40多年的發(fā)展,SQL已經(jīng)成為訪(fǎng)問(wèn)數(shù)據(jù)的通用語(yǔ)言。一套數(shù)據(jù)庫(kù)系統(tǒng)不支持SQL語(yǔ)言就意味著要求開(kāi)發(fā)者學(xué)習(xí)不同的訪(fǎng)問(wèn)數(shù)據(jù)的語(yǔ)言。
NoSQL數(shù)據(jù)庫(kù)在網(wǎng)頁(yè)擴(kuò)展、大數(shù)據(jù)和分析部署等方面越來(lái)越流行。每一個(gè)種類(lèi)的NoSQL數(shù)據(jù)庫(kù)都有適用的不同類(lèi)型的應(yīng)用程序和用例,這就涉及到一個(gè)NoSQL社區(qū)常用的一個(gè)話(huà)題,即多樣持久性,或者說(shuō)根據(jù)數(shù)據(jù)庫(kù)處理應(yīng)用程序需求的不同,使用不同的數(shù)據(jù)庫(kù)系統(tǒng),用于不同的應(yīng)用程序和用例。因此,使用NoSQL最重要的是使用正確的數(shù)據(jù)庫(kù),滿(mǎn)足具體的需求,哪怕是要引入一種新的數(shù)據(jù)庫(kù)系統(tǒng)。
2 MongoDB
2.1 簡(jiǎn)述
MongoDB是一個(gè)高性能,開(kāi)源,可擴(kuò)展,無(wú)模式的文檔型數(shù)據(jù)庫(kù),由C++語(yǔ)言編寫(xiě)。旨在為WEB應(yīng)用提供可擴(kuò)展的高性能數(shù)據(jù)存儲(chǔ)解決方案,是當(dāng)前NoSql數(shù)據(jù)庫(kù)中比較熱門(mén)的一種。它是一個(gè)介于關(guān)系數(shù)據(jù)庫(kù)和非關(guān)系數(shù)據(jù)庫(kù)之間的產(chǎn)品,是非關(guān)系數(shù)據(jù)庫(kù)當(dāng)中功能最豐富,最像關(guān)系數(shù)據(jù)庫(kù)的。支持的數(shù)據(jù)結(jié)構(gòu)非常松散,是類(lèi)似json的bson格式,因此可以存儲(chǔ)比較復(fù)雜的數(shù)據(jù)類(lèi)型。Mongo最大的特點(diǎn)是他支持的查詢(xún)語(yǔ)言非常強(qiáng)大,其語(yǔ)法有點(diǎn)類(lèi)似于面向?qū)ο蟮牟樵?xún)語(yǔ)言,幾乎可以實(shí)現(xiàn)類(lèi)似關(guān)系數(shù)據(jù)庫(kù)單表查詢(xún)的絕大部分功能,而且還支持對(duì)數(shù)據(jù)建立索引。
傳統(tǒng)的關(guān)系數(shù)據(jù)庫(kù)一般由數(shù)據(jù)庫(kù)(database)、表(table)、記錄(record)三個(gè)層次概念組成,MongoDB是由數(shù)據(jù)庫(kù)(database)、集合(collection)、文檔對(duì)象(document)三個(gè)層次組成。集合對(duì)應(yīng)于關(guān)系型數(shù)據(jù)庫(kù)里的表,但是集合中沒(méi)有列、行和關(guān)系概念,這體現(xiàn)了其模式自由的特點(diǎn)。
它的特點(diǎn)是高性能、易部署、易使用,存儲(chǔ)數(shù)據(jù)非常方便。主要功能特性有:
1)面向集合存儲(chǔ),易存儲(chǔ)對(duì)象類(lèi)型的數(shù)據(jù)。
2)模式自由。
3)支持動(dòng)態(tài)查詢(xún)。
4)支持完全索引,包含內(nèi)部對(duì)象。
5)支持查詢(xún)。
6)支持復(fù)制和故障恢復(fù)。
7)使用高效的二進(jìn)制數(shù)據(jù)存儲(chǔ),包括大型對(duì)象(如視頻等)。
8)自動(dòng)處理碎片,以支持云計(jì)算層次的擴(kuò)展性。
9)支持RUBY,PYTHON,JAVA,C++,PHP,C#等多種語(yǔ)言。
10)文件存儲(chǔ)格式為BSON(一種JSON的擴(kuò)展)。
11)可通過(guò)網(wǎng)絡(luò)訪(fǎng)問(wèn)。
所謂“面向集合”(Collenction-Oriented),意思是數(shù)據(jù)被分組存儲(chǔ)在數(shù)據(jù)集中,被稱(chēng)為一個(gè)集合(Collenction)。每個(gè)集合在數(shù)據(jù)庫(kù)中都有一個(gè)唯一的標(biāo)識(shí)名,并且可以包含無(wú)限數(shù)目的文檔。集合的概念類(lèi)似關(guān)系型數(shù)據(jù)庫(kù)(RDBMS)里的表(table),不同的是它不需要定義任何模式(schema)。
模式自由(schema-free),意味著對(duì)于存儲(chǔ)在mongodb數(shù)據(jù)庫(kù)中的文件,我們不需要知道它的任何結(jié)構(gòu)定義。如果需要的話(huà),你完全可以把不同結(jié)構(gòu)的文件存儲(chǔ)在同一個(gè)數(shù)據(jù)庫(kù)里。
存儲(chǔ)在集合中的文檔,被存儲(chǔ)為鍵一值對(duì)的形式。鍵用于唯一標(biāo)識(shí)一個(gè)文檔,為字符串類(lèi)型,而值則可以是各種復(fù)雜的文件類(lèi)型。我們稱(chēng)這種存儲(chǔ)形式為BSON(Binary JSON)。
2.2 Mongodb安裝配置
根據(jù)自己的實(shí)際系統(tǒng)環(huán)境,下載所要的文件,我的是RHEL 7 Linux 64-bit。下載:
# wget https: //fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhe170-3.0.7.tgz解壓至/usr/local/mongodb/,創(chuàng)建數(shù)據(jù)目錄/data/mongodb,創(chuàng)建配置文件mongodb.conf。配置文件mongodb.conf如下,其中dbpath指定數(shù)據(jù)庫(kù)目錄,logpath指定日志路徑,logappend=true使日志累加,fork=true使MongoDB以守護(hù)進(jìn)程運(yùn)行,port指定端口號(hào),默認(rèn)27017。
dbpath=/data/mongo/
logpath=/data/mongo/mongo.log
logappend=true
fork=true
port=27017
MongoDB有兩種啟動(dòng)方式,配置文件啟動(dòng)和參數(shù)啟動(dòng),如下:
1.配置文件方式啟動(dòng)mongo
#/usr/local/mongodb/bin/mongod -f/data/mongo/mongodb.conf
2.參數(shù)啟動(dòng)mongo
/usr/local/mongodb/bin/mongod -logpath /data/mongo/mongo.log -logappend -fork -dbpath /data/mongo/-port 27017
3.設(shè)置開(kāi)機(jī)啟動(dòng):
#echo“/usr/local/mongodb/bin/mongod—f/data/mongo/mongodb.conf”>>/etc/rc.local
3 氣象傳感器數(shù)據(jù)在mongo系統(tǒng)中的存儲(chǔ)
3.1 數(shù)據(jù)的插入
使用Python創(chuàng)建數(shù)據(jù)庫(kù)的方法如下:
client=MongoClient()
db=client.meteor_data
collection=db.res
連接到mongo數(shù)據(jù)庫(kù)metor_data,并選中集合(cellection) res,注意:這里并沒(méi)有創(chuàng)建集合,mongo采用延時(shí)創(chuàng)建的方法,當(dāng)有document插入時(shí)才真正創(chuàng)建相應(yīng)的數(shù)據(jù)庫(kù)和集合。
如下所示是一條測(cè)量數(shù)據(jù),‘CHIO代表通道10的測(cè)量數(shù)據(jù),102941.437對(duì)應(yīng)氣象參數(shù)的傳感器測(cè)量值。每條測(cè)量數(shù)據(jù)中通道數(shù)并不固定,可以根據(jù)測(cè)量需要選擇。‘TIME則代表測(cè)量的時(shí)刻。
{u'CHl0':102941.437,u'TIME':'2015-09-22 20:33: 10',u'CH5': 918.236714, u'CH6':270.424495,u'CH7': 328.123456, u'CH8':465.627787,u'CH9':386.63469}
我們通過(guò)把多條測(cè)量數(shù)據(jù)作為document插入集合res中,來(lái)存儲(chǔ)測(cè)量數(shù)據(jù),python插入document的方法為:collection.insert_one(data),其中date代表要插入的測(cè)量數(shù)據(jù)。插入后的document如下。其中,'_id'域?yàn)閙ongo為我們自動(dòng)添加的,作為主鍵。
{u'CHl0':102941.437,u'TIME':u'2015-09-22 20:33:10', u'CH5': 918.236714, u'CH6':270.424495, u'CH7':328.123456,u'CH8':465.627787,u'CH9':386.63469, u'_id': Objectld('563afebee138233a73b2at20')}
3.2 數(shù)據(jù)的查詢(xún)
測(cè)量數(shù)據(jù)存儲(chǔ)后,我們可以很方便的去查詢(xún),有相等匹配(equality matching)和條件匹配。相等匹配格式為:{
3.3 更新
集合更新的python接口有update_one()和update_many(),更新時(shí)需指定過(guò)濾條件和匹配的document要執(zhí)行的動(dòng)作。如result=collection.update_one({'TIME': '2015-09-22 20:33:10'},{“$set”:{"discription":“measure resistance”}}),會(huì)先匹配‘TIME域?yàn)椤?015-09-22 20: 33: 10的記錄,然后更新其”discription”域的值為”measure resistance”,若沒(méi)有該域,則會(huì)添加該域。其中,”$set”為設(shè)定域值運(yùn)算符,其他更新運(yùn)算符:”$inc”為指定域的值增加指定值,”$rename”用于重命名域名,”$push”向域值列表中添加元素。更新后的document為:
{u'CH10':102941.437, u'TIME': u'2015-09-22 20: 33: 10,u'discription': u'measure resistance',u'CH5': 918.236714, u'CH6': 270.424495, u'CH7':328.123456, u'CH8': 465.627787, u'CH9': 386.63469,u'_id':Objectld('563afebee138233a73b2af20')
3.4 聚合
MongoDB提供了一個(gè)聚合框架,其中包括常用功能,比如”$match”用于過(guò)濾記錄、“$unwind”用于解綁列表、“$group”用于根據(jù)指定域聚合。其聚合是基于階段( stage)來(lái)進(jìn)行的,其參數(shù)為一個(gè)個(gè)階段組成的列表,格式如下:db.collection.aggregate([
cursor=collection.aggregate(
[
{“$match”:{“CH5”:None}},
{“$group”:{“_id”:“$CH5”,“count”:{“$sum”:1}}}
]
)
此聚合首先在第一階段匹配”CH5”域不存在的記錄,第二階段以”CH5”域的值分組,并以“id”作為key,統(tǒng)計(jì)各組記錄的數(shù)量,由于第一階段只匹配”CH5”域不存在的組,所以該聚合統(tǒng)計(jì)的是集合中”CH5”域不存在的記錄數(shù)。結(jié)果如下:
然而更多的高級(jí)聚合函數(shù),比如sum、average、max、min、variance方差)和standard deviation(標(biāo)準(zhǔn)差)等需要通過(guò)MapReduce來(lái)實(shí)現(xiàn)。
4 結(jié)論
MongoDB提供了面向文檔的存儲(chǔ)結(jié)構(gòu),其模式十分自由,這很大程度增加了document的靈活性,可以很容易擴(kuò)展支持TB級(jí)數(shù)據(jù)。同時(shí)其插入、查詢(xún)、更新、聚合等操作也十分方便簡(jiǎn)易,支持C++、Python、Java等多種語(yǔ)言。本文結(jié)合實(shí)驗(yàn)室氣象局研究項(xiàng)目,介紹了MongoDB的安裝,以及它在氣象傳感器數(shù)據(jù)存儲(chǔ)時(shí)的應(yīng)用,項(xiàng)目實(shí)踐證明了其靈活、易用等優(yōu)點(diǎn)。相信在不久的將來(lái)以MongoDB為代表的Nosql將有更加廣泛的應(yīng)用。