呂瓊帥,張國平
(平頂山學(xué)院 軟 件學(xué)院, 河南 平 頂山 4 67000)
Lucene是Apache軟件基金會(huì)項(xiàng)目組的子項(xiàng)目,是一個(gè)開放源代碼的全文檢索引擎工具包,即它不是一個(gè)完整的全文檢索引擎,而是一個(gè)全文檢索引擎的架構(gòu),提供了完整的查詢引擎、索引引擎和部分文本分析引擎。Lucene的目的是為軟件開發(fā)人員提供一個(gè)簡單易用的工具包,以方便的在目標(biāo)系統(tǒng)中實(shí)現(xiàn)全文檢索的功能,或者是以此為基礎(chǔ)建立起完整的全文檢索引擎。Lucene作為一個(gè)全文檢索引擎,其具有索引文件格式獨(dú)立于應(yīng)用平臺(tái)、優(yōu)秀的面向?qū)ο笙到y(tǒng)架構(gòu)等突出的優(yōu)點(diǎn)。但是,Lucene索引和查詢都不方便,容易受到索引文件數(shù)量的制約,這樣便會(huì)影響數(shù)據(jù)庫運(yùn)行性能,降低檢索的效率。
隨著Web2.0技術(shù)的興起,NoSQL這個(gè)概念也逐漸被人們所熟悉。NoSQL最早出現(xiàn)于1998年,是非關(guān)系型數(shù)據(jù)庫的總稱,由Carlo Strozzi開發(fā)的一個(gè)輕量、開源、不提供SQL功能的關(guān)系數(shù)據(jù)庫[1]。2009年,Last.fm的Johan Oskarsson發(fā)起了一次關(guān)于分布式開源數(shù)據(jù)庫的討論,來自Rackspace的Eric Evans再次提出了NoSQL的概念[2]。目前主要的NoSQL產(chǎn) 品 主 要 有 MemCahe,Redis,Tokyo Tyrant,MongDB,HBase。NoSQL主要指非關(guān)系型、分布式、不提供ACID的數(shù)據(jù)庫設(shè)計(jì)模式,強(qiáng)調(diào)Key-Value Stores和文檔數(shù)據(jù)庫的優(yōu)點(diǎn),而并不是單純的反對(duì)RDBMS。并且NoSQL是以CAP、BASE以及最終一致性為其理論基礎(chǔ),是針對(duì)目前大規(guī)模數(shù)據(jù)的高并發(fā)讀寫,高效存儲(chǔ),高可用性等用戶需求而出現(xiàn)的一種較新的數(shù)據(jù)存儲(chǔ)機(jī)制。NoSQL之所以能夠快速發(fā)展,主要依賴于用戶對(duì)后臺(tái)數(shù)據(jù)庫的高并發(fā)讀寫的需求和對(duì)海量數(shù)據(jù)的高速訪問的需求?;谶@樣一個(gè)優(yōu)勢(shì),本文將非關(guān)系型數(shù)據(jù)庫引入到Lucene全文檢索系統(tǒng)中,以此來應(yīng)對(duì)大規(guī)模數(shù)據(jù)的高效存儲(chǔ)與高效檢索問題。
MemCache是由Danga Interactive公司開發(fā)的開源軟件,屬于臨時(shí)性鍵值存儲(chǔ)的NoSQL數(shù)據(jù)庫[3]。MemCache是通過散列表來存儲(chǔ)各種格式數(shù)據(jù)的鍵值存儲(chǔ),所有的數(shù)據(jù)都被保存在內(nèi)存中。
MemCache利用簡單的文本協(xié)議來進(jìn)行數(shù)據(jù)通信,數(shù)據(jù)操作也只是類似于保存與鍵值相對(duì)應(yīng)的值來進(jìn)行簡單的處理。因此,通過Telnet連接MemCache,就可以進(jìn)行數(shù)據(jù)的保存和讀取。MemCache的優(yōu)勢(shì)主要就是其處理速度比較快。對(duì)于MemCache要處理的數(shù)據(jù)全部存儲(chǔ)于內(nèi)存中,因此不需要訪問外部設(shè)備,那么在進(jìn)行數(shù)據(jù)處理時(shí)就能夠比關(guān)系型數(shù)據(jù)庫高出很多的速度來運(yùn)行。另外,MemCache在應(yīng)用方面也比較簡單,在進(jìn)行數(shù)據(jù)的操作時(shí),主要是基于鍵值散列表的形式來進(jìn)行的。但是隨著數(shù)據(jù)量的增加,MemCache的內(nèi)存無法保存所有的數(shù)據(jù),這時(shí)可以使用多臺(tái)服務(wù)器來運(yùn)行MemCache,通過使用一致性散列算法[4]來將數(shù)據(jù)分散到多臺(tái)服務(wù)器上來運(yùn)行MemCache。
一致性散列算法對(duì)各個(gè)服務(wù)器對(duì)應(yīng)的散列值進(jìn)行計(jì)算,把它們配置到一個(gè)圓周上。同時(shí)對(duì)各個(gè)數(shù)據(jù)對(duì)應(yīng)的鍵的散列值進(jìn)行計(jì)算,從鍵的散列值出發(fā)沿圓周向右,由距離該散列值最近的服務(wù)器來負(fù)責(zé)處理這條數(shù)據(jù)(數(shù)據(jù)的保存、讀取都由這個(gè)服務(wù)器來完成)。如圖1一致性散列分配方式。
圖1 一致性散列分配方式Fig.1 Consistent hashing allocation
MongoDB是10gen公司開發(fā)的一款以高性能和可擴(kuò)展性為特征的開源軟件,它是NoSQL數(shù)據(jù)庫中面向文檔的數(shù)據(jù)庫[5]。MongoDB最大的特點(diǎn)就是無表結(jié)構(gòu)。由于它無需定義表結(jié)構(gòu),所以對(duì)于任何Key都可以像關(guān)系型數(shù)據(jù)庫那樣進(jìn)行復(fù)雜查詢等操作。MongoDB有比關(guān)系型數(shù)據(jù)庫更快的操作速度,而且可以像關(guān)系型數(shù)據(jù)庫那樣通過添加索引來進(jìn)行高速處理。
MongoDB在保存數(shù)據(jù)的時(shí)候會(huì)把數(shù)據(jù)和數(shù)據(jù)結(jié)構(gòu)都完整地以BSON(JSON的二級(jí)制化形式)的形式保存起來,并把它作為值和特定的鍵記性關(guān)聯(lián)。MongoDB采用面向文檔的數(shù)據(jù)模型,以文檔為單位存儲(chǔ)數(shù)據(jù),每個(gè)文檔內(nèi)的字段允許有不同的設(shè)置,可以動(dòng)態(tài)修改數(shù)據(jù)結(jié)構(gòu)模式。MongoDB使用自動(dòng)分片機(jī)制實(shí)現(xiàn)分布式擴(kuò)展,可以將數(shù)據(jù)庫中的集合、文檔分布存儲(chǔ)在多個(gè)數(shù)據(jù)庫節(jié)點(diǎn)。自動(dòng)分片機(jī)制以集合為單位進(jìn)行分片,選擇集合的一個(gè)或多個(gè)自動(dòng)作為分片鍵,按分片鍵排序集合文檔,將集合分成多個(gè)塊存儲(chǔ)到不同的分片上。
對(duì)于基于Lucene的全文檢索系統(tǒng)來說,應(yīng)用在高并發(fā)的讀寫和高效的存儲(chǔ)的情況下會(huì)使檢索的效率比較低,因?yàn)樵撓到y(tǒng)需要提供多種格式的文檔的全文和元數(shù)據(jù)的存儲(chǔ)檢索查詢服務(wù)。對(duì)于中文的編碼問題,如果采用不同的編碼方式就會(huì)占用不同的存儲(chǔ)空間,檢索的效率就會(huì)降低。在高并發(fā)操作的時(shí)候,如果保存包含域的文件比較大時(shí),在進(jìn)行檢索時(shí)會(huì)浪費(fèi)比較多的時(shí)間,檢索性能會(huì)有明顯的下降。而對(duì)于Lucene自身所采用的緩存機(jī)制來說,當(dāng)該對(duì)象不存在了其對(duì)應(yīng)的緩存并沒有回收。而該對(duì)象再次調(diào)用的時(shí)候又會(huì)重新分配新的內(nèi)存,最終會(huì)出現(xiàn)內(nèi)存泄露的問題。針對(duì)這些問題,本文給出一種具有高并發(fā)性和可擴(kuò)展性的系統(tǒng)架構(gòu)。
在對(duì)系統(tǒng)進(jìn)行整體的設(shè)計(jì)時(shí),將系統(tǒng)大體劃分為3層:上層的應(yīng)用層,中間的數(shù)據(jù)服務(wù)層,底部的數(shù)據(jù)化持久層。如圖2整體架構(gòu)。
圖2 整體架構(gòu)Fig.2 Overall architecture
其中上層應(yīng)用層主要指Web服務(wù)層(包含客戶端),用來接受和應(yīng)答用戶請(qǐng)求,比如對(duì)文檔進(jìn)行檢索、處理、存儲(chǔ),并返回檢索信息等。中間數(shù)據(jù)服務(wù)層負(fù)責(zé)與底層交換數(shù)據(jù)同時(shí)屏蔽底層不同服務(wù)向上層提供統(tǒng)一的調(diào)用接口。底層服務(wù)包括文檔檢索服務(wù)實(shí)現(xiàn)層和數(shù)據(jù)持久化層,實(shí)現(xiàn)具體的業(yè)務(wù)邏輯,是系統(tǒng)的基礎(chǔ)。
在高并發(fā)讀寫,高效存儲(chǔ)的過程中,針對(duì)Lucene的低效存儲(chǔ)和面對(duì)較大的索引文件時(shí)檢索效率較低的問題,考慮減小索引文件的大小,將索引文件中的不重要的信息作為一個(gè)節(jié)點(diǎn)從索引文件中分離出去,而索引中僅存放較為重要的信息,如將ID和指向節(jié)點(diǎn)相關(guān)信息存放在MongoDB中,而將節(jié)點(diǎn)存放在MySQL中。這樣可以明顯加快檢索的速度,提高緩存的效率,而當(dāng)需要訪問整個(gè)文件的信息時(shí)再從關(guān)系型數(shù)據(jù)庫中提取。具體方案如圖3所示。
圖3 NoSQL同步鏡像示意圖Fig.3 NoSQL Synchronous mirror
中間的數(shù)據(jù)服務(wù)層需要響應(yīng)上層的用戶請(qǐng)求,并且需要調(diào)用下層服務(wù),接受下層服務(wù)返回的數(shù)據(jù),然后返回給上層用戶結(jié)果。在監(jiān)聽用戶的請(qǐng)求時(shí),本文選擇了Apache MINA作為中間層的解決方案,MINA通過Java NIO提供了一種抽象的異步通訊API,使用MINA能夠便捷的進(jìn)行非阻塞I/O而不用考慮過多的傳輸細(xì)節(jié),并且是事件驅(qū)動(dòng)的方式[6]。在監(jiān)聽到請(qǐng)求后需要對(duì)事件進(jìn)行處理,本系統(tǒng)選擇了規(guī)則引擎Drools作為事件處理邏輯單元的解決方案。Drools實(shí)現(xiàn)了邏輯與數(shù)據(jù)的分離,數(shù)據(jù)保存在系統(tǒng)對(duì)象中,邏輯保存在規(guī)則中,可以使用更接近自然語言的方式來編寫規(guī)則[7]。并且規(guī)則相對(duì)于編碼更容易對(duì)復(fù)雜問題進(jìn)行描述。因此,使用規(guī)則引擎滿足上文描述的事件處理邏輯的需求,可以用規(guī)則引擎來實(shí)現(xiàn)中間數(shù)據(jù)服務(wù)層的核心部分。中間數(shù)據(jù)服務(wù)層的執(zhí)行流程如圖4所示。
圖4 服務(wù)層運(yùn)行流程Fig.4 Service layer running processes
上層的應(yīng)用層主要用來接收用戶的請(qǐng)求,并利用應(yīng)用層的緩存層來暫存檢索的結(jié)果,為了提高檢索的速度,本文主要采用MemCache來構(gòu)建應(yīng)用層的緩存框架,因?yàn)镸emCache的主要優(yōu)勢(shì)就是其極快的處理速度,如果緩存中存有數(shù)據(jù),根本不需要去進(jìn)行I/O操作。另外在使用MemCache的過程中,其安裝使用也比較方便,如果在運(yùn)行過程中遇到難以處理的問題,只要重新啟動(dòng)MemCache就可以恢復(fù)到初始狀態(tài)。為了應(yīng)對(duì)數(shù)據(jù)量的巨增,在系統(tǒng)架構(gòu)時(shí)通過多臺(tái)服務(wù)器來運(yùn)行MemCache。
圖5 MemCache使用方法Fig.5 The method used MemCache
將三層進(jìn)行整合后,當(dāng)客戶端發(fā)起查詢請(qǐng)求時(shí),會(huì)先去查看緩存中是否含有查詢的請(qǐng)求,如果有則直接返回結(jié)果,反之,根據(jù)查詢分析器和規(guī)則庫將查詢請(qǐng)求規(guī)范化后,搜索數(shù)據(jù)庫中的索引文件,把結(jié)果返回給客戶端,同時(shí)將規(guī)范化后的客戶請(qǐng)求保存在緩存中。
實(shí)驗(yàn)主要從檢索的響應(yīng)時(shí)間來測(cè)試該系統(tǒng)架構(gòu)的性能。如圖6,其中橫軸表示文檔的數(shù)量,縱軸表示檢索時(shí)間。其中LST表示僅在使用Lucene時(shí)掃描索引文件的時(shí)間,NST表示基于NoSQL的掃描索引文件的時(shí)間;LRT表示僅在使用Lucene時(shí)搜索的響應(yīng)時(shí)間,NRT表示基于NoSQL的搜索響應(yīng)時(shí)間。
圖6 響應(yīng)時(shí)間Fig.6 Response time
從圖6的實(shí)驗(yàn)結(jié)果可以看出,隨著文檔數(shù)量的增加,僅使用Lucene的全文檢索系統(tǒng)和基于NoSQL的全文檢索系統(tǒng)的響應(yīng)時(shí)間都在逐漸增大,但Lucene的全文檢索系統(tǒng)響應(yīng)時(shí)間增加的比較明顯,基于NoSQL的全文檢索系統(tǒng)的響應(yīng)時(shí)間大體上保持相對(duì)穩(wěn)定。
該系統(tǒng)將NoSQL技術(shù)引入到Lucene的全文檢索過程中,克服了Lucene在應(yīng)對(duì)數(shù)據(jù)的高并發(fā)性方面檢索速度慢的缺陷。系統(tǒng)在架構(gòu)時(shí)采用分層的設(shè)計(jì)思想,使系統(tǒng)層次間具有低耦合,層次內(nèi)部具有高內(nèi)聚的特點(diǎn),通過實(shí)驗(yàn)表明該系統(tǒng)在應(yīng)對(duì)高并發(fā)性和高效檢索問題時(shí)具有較快的響應(yīng)速度,且系統(tǒng)運(yùn)行過程中較為穩(wěn)定。
[1]Lith, Adam,Jakob Mattson.Investigating storage solutions for large data:A comparison of well performing and scalable data storage solutions for real time extraction and batch insertion of data[D].oteborg Sweden:Chalmers University of Technology,2010.
[2]謝毅.NoSQL非關(guān)系型數(shù)據(jù)庫綜述[J].先進(jìn)技術(shù)研究通報(bào),2010,4(8):46-50.XIE Yi.NoSQL Summary of non-relational databases[J].Bulletin of Advanced Technology Research,2010,4(8):46-50.
[3]陸嘉恒.大數(shù)據(jù)挑戰(zhàn)與NoSQL數(shù)據(jù)庫技術(shù)[M].北京:電子工業(yè)出版社,2013.
[4]姚琳,張永庫.NoSQL的分布式存儲(chǔ)與擴(kuò)展解決方法[J].計(jì)算機(jī)工程,2012,38(6):40-42.YAO Lin,ZHANG Yong-ku.Solution of NoSQL distributed storage and extension[J].Computer Engineering,2012,38(6):40-42.
[5]沈姝.NoSQL數(shù)據(jù)庫技術(shù)及其應(yīng)用研究[D].南京:南京信息工程大學(xué),2012.
[6]曾冠東.基于MINA構(gòu)建簡單高性能的NIO應(yīng)用[J].程序員,2008(2):120-123.ZENG Guan-dong.Building a simple high-performance NIO application based on MINA[J].Programmer,2008(2):120-123.
[7]劉金龍.drools規(guī)則引擎模式匹配效率優(yōu)化研究及實(shí)現(xiàn)[D].成都:西南交通大學(xué),2007.