朱松杰,婁淵勝,葉 楓,,李 凌,陳 勇
1.河海大學 計算機與信息學院,南京211100
2.南京龍淵微電子科技有限公司 博后工作站,南京211106
隨著大數(shù)據(jù)時代的到來,傳統(tǒng)的關系型數(shù)據(jù)庫難以處理無規(guī)范模式的數(shù)據(jù)集,并且隨著數(shù)據(jù)集規(guī)模的增大,不能提供高效的存儲和查詢服務,也不能滿足系統(tǒng)的新需求。互聯(lián)網(wǎng)先驅不得不重新設計數(shù)據(jù)庫,大數(shù)據(jù)系統(tǒng)和NoSQL(Not-Only-SQL即非關系型數(shù)據(jù)庫)越來越多地被開發(fā)出來,例如Facebook的Cassandra、Amazon的Dynamo 以及支持高效數(shù)據(jù)查詢的內(nèi)存數(shù)據(jù)存儲系統(tǒng)Redis等[1]。這些數(shù)據(jù)庫的數(shù)據(jù)存儲都采用了key-value數(shù)據(jù)模型,HBase 便是key-value 數(shù)據(jù)庫中使用最為廣泛的[2]。
在Google 的BigTable 論文的發(fā)表后,Cafarella 在Hadoop 上面實現(xiàn)了BigTable 的一個開源版本,被稱為HBase[3]。HBase由多個軟件子系統(tǒng)組成,主要包括客戶端、HMaster、HRegionServer、Zookeeper 等,這些子系統(tǒng)共同組成一個分布式應用系統(tǒng),它具有開源、分布式、可擴展及面向列存儲的特點,能夠為大數(shù)據(jù)提供隨機、實時的讀寫訪問功能。如何從海量數(shù)據(jù)中快速獲得所需數(shù)據(jù)是使用HBase 等NoSQL 數(shù)據(jù)庫的一個重要原因,HBase在其主鍵上建立了B+樹索引,在使用主鍵進行查詢時效率很高[4]。但是,在進行非主鍵的條件查詢時,由于缺少主鍵的支撐,HBase 必須進行全表掃描,導致查詢效率低下,無法滿足上述要求。對此,本文在借鑒關系型數(shù)據(jù)庫解決方案的基礎上,提出了一種基于二級索引的查詢機制,并將索引數(shù)據(jù)存儲在內(nèi)存數(shù)據(jù)庫中,通過內(nèi)存進行二級索引檢索,進一步提高了對大數(shù)據(jù)的實時查詢響應。
HBase 是一個構建在HDFS 之上,用于海量數(shù)據(jù)存儲分布式列存儲系統(tǒng)[5]。HBase 表的每行都是按照RowKey 的字典序排序存儲,每行數(shù)據(jù)是按照RowKey區(qū)間進行分割存儲成多個Region。HBase 只針對行健的索引,在原生產(chǎn)品中訪問HBase表中的行只能通過行健訪問,行健區(qū)間訪問和全表掃描三種。
當前,國內(nèi)許多使用HBase的企業(yè)或者個人都會對其建立索引來提高性能,比較常見的有基于Coprocessor方案,如華為的HIndex方案和Apache Phoenix方案[6]。其支持自定義數(shù)據(jù)處理邏輯,采用數(shù)據(jù)“雙寫”(dual-write)策略,在有數(shù)據(jù)寫入時同時同步到二級索引表。相比于華為的HIndex,Apache Phoenix 的版本迭代情況較好,支持和兼容多個HBase版本,二級索引只是其中一塊功能[6]。同時,二級索引的創(chuàng)建和管理直接有SQL語法的支持,使用簡單。王文賢等人[7]實現(xiàn)了一種基于Solr 的HBase海量數(shù)據(jù)二級索引方案,該方案主要對華為Hindex進行改進,其基于數(shù)據(jù)存儲和索引分離的思想,將Solr 檢索與HBase 的大數(shù)據(jù)存儲結合起來,具有一定的通用性。丁飛等人[4]實現(xiàn)了基于協(xié)處理器的HBase區(qū)域級服務端區(qū)域級第二索引擴展功能,索引存儲格式選HBase自身的數(shù)據(jù)組織方式,即HFile文件格式。利用HFile高效的IO性能保證索引查詢的效率。周偉等人[8]對HBase分布式二級索引通用方案進行研究,引入分布式索引機制,在SolrCloud中完成對索引的管理,借助協(xié)處理器提供的索引功能為HBase記錄創(chuàng)建、存儲索引,其中HBase負責存儲數(shù)據(jù),Solr負責索引數(shù)據(jù)和檢索。
許多研究者已經(jīng)使用Coprocessor 來構建HBase 二級索引,具體有兩種解決方案:一種是直接存儲到數(shù)據(jù)庫或文件中實現(xiàn)索引持久化,但這種方法的索引檢索效率較低,另一種是通過構建內(nèi)存索引,并存儲到特定環(huán)境中實現(xiàn)持久化。從開發(fā)設計的角度看,把很多對二級索引管理的細節(jié)都封裝在的Coprocessor具體實現(xiàn)類里面,這些細節(jié)對外面讀寫的人是無感知的,簡化了數(shù)據(jù)訪問者的使用。雖然具有一定的入侵性,會對Region-Server性能產(chǎn)生一定影響。
對于非Coprocessor方案,不基于Coprocessor開發(fā),而是自行在外部構建和維護索引關系。常見的是采用底層基于Apache Lucene 的Elasticsearch[9],來構建強大的索引能力、搜索能力,例如支持模糊查詢、全文檢索、組合查詢、排序等。LilyHBase Indexer(也簡稱HBase Indexer)是國外的NGDATA公司開源的基于solr的索引構建工具,特色是其基于HBase 的備份機制,開發(fā)了一個叫SEP工具,通過監(jiān)控HBase的WAL日志(Put/Delete操作),來觸發(fā)對solr 集群索引的異步更新,基本對HBase無侵入性[10]。葛微等人[3]提出了名為HiBase的二級索引,它是一種基于分層式索引的設計方案,其將熱點索引進行緩存,并建立高效的緩存替換策略來提高二級索引的查詢速度。Zou 等提出了互補聚簇式索引(Complemental Clustering Index,CCIndex),該方案把數(shù)據(jù)的詳細信息也存放在索引表中,不需要通過獲取的行鍵再到原表中去查找數(shù)據(jù)。使用非Coprocessor方案時,如存儲開銷比較大,尤其是當索引列比較多的時候,空間開銷會更大。索引更新代價比較高,會影響系統(tǒng)的吞吐量,索引創(chuàng)建以后,不能夠動態(tài)增加或修改。
綜上,本文使用基于觀察者模式的Coprocessor 方法實現(xiàn)二級索引功能,并通過分布式存儲保證二級索引的高可用和高容錯性。提出了基于Coprocessor的索引構建方案,并且針對協(xié)處理器索引檢索速度問題,構建了內(nèi)存索引,意圖是提高索引檢索速度。
所提機制的總體結構如圖1所示。其中,索引管理模塊是框架核心,在用戶對數(shù)據(jù)表進行更新操作時,協(xié)處理器Coprocessor 會對這些請求進行攔截,并對索引表進行相應操作,包括插入、刪除和更新索引的元數(shù)據(jù)(記錄用戶表對應的索引表名稱、索引列等信息)。執(zhí)行查詢操作時,系統(tǒng)會在緩存中尋找對應索引位置,提高了索引檢索速度,當緩存中的索引更新時,索引管理模塊也會對索引進行更新。索引持久化管理模塊主要對緩存索引進行持久化操作,提供索引表和值表的持久化存儲,HBase為持久化存儲數(shù)據(jù)提供可擴展性和容錯性。
圖1 系統(tǒng)總體結構圖
由于HBase無法定制服務端邏輯,使得用戶無法在服務端實現(xiàn)自己需求的二級索引方案,HBase在0.92版本中引入了協(xié)處理器Coprocessor 機制,它受啟發(fā)于Google 的Bigtable 的協(xié)處理器,為實現(xiàn)建立二次索引、復雜過濾器(謂詞下推)以及訪問控制等提供了一種很好的解決方案[11]。協(xié)處理器是一種服務端組件,類似于輕量級的MapReduce,它的主要思想是通過將集群內(nèi)的數(shù)據(jù)移動取代為計算移動來減少計算代價,提高效率。其可理解為服務端的攔截器,可根據(jù)需求確定攔截點,再重寫這些攔截點對應的方法。協(xié)處理器允許在Region服務器上運行自己的代碼,更準確地說是允許用戶執(zhí)行Region級的操作,并且可以使用與RDBMS中觸發(fā)器(trigger)類似的功能。
Coprocessor可以分為兩大類:Observer Coprocessors(觀察者)和EndPoint Coprocessor(終端)。Observer Coprocessor在一個特定的事件發(fā)生前或發(fā)生后觸發(fā),其工作過程如圖2所示。
圖2 協(xié)處理器工作過程
Observer Coprocessor使用場景如下。
(1)安全性:在執(zhí)行Get 或Put 操作前,通過preGet或prePut方法檢查是否允許該操作。
(2)引用完整性約束:HBase 并不直接支持關系型數(shù)據(jù)庫中的引用完整性約束概念,即通常所說的外鍵。但是,可以使用Coprocessor增強這種約束。
(3)二級索引:可以使用Coprocessor 來維持一個二級索引。
Endpoint協(xié)處理器類似傳統(tǒng)數(shù)據(jù)庫中的存儲過程,客戶端可以調(diào)用這些Endpoint協(xié)處理器執(zhí)行一段Server端代碼,并將Server 端代碼的結果返回給客戶端進一步處理[12]。利用Coprocessor,用戶可以將代碼部署到HBase Server 端,HBase 將利用底層cluster 的多個節(jié)點并發(fā)執(zhí)行。Endpoint 不僅能與客戶端通信,而且能與Observer 進行通信。Observer 可以在回調(diào)方法里通知Endpoint,執(zhí)行一定的事件響應邏輯。兩種處理器的共同協(xié)作可以定制功能強大的HBase應用,既可以實現(xiàn)對集群中每個Region數(shù)據(jù)變更的監(jiān)控,又可以通過Endpoint將處理結果返回給客戶端。
協(xié)處理器機制支持用戶根據(jù)業(yè)務要求,重寫Endpoint和Observer代碼,本文使用Observer協(xié)處理器來進行索引的構建。Observer 協(xié)處理器類似于關系型數(shù)據(jù)庫中的觸發(fā)器,當對數(shù)據(jù)庫進行增刪改查操作時,Observer會對這些請求進行攔截,并根據(jù)這些請求,實時更新索引表。二級索引的整體架構圖如圖3所示。
圖3 二級索引架構圖
建立的索引結構如圖3 所示,采用了倒排的方法,將數(shù)據(jù)表的值與主鍵進行交換,原本的值充當主鍵,原本的主鍵放在值的位置,一個最基本的索引表即構建完畢。在未建立索引前,HBase的數(shù)據(jù)模型可形式化表示為:
其中行健為R,列族為C ,列限定符為CQ,時間戳為T ,值為V 。則二級索引的形式化表示為:Vi→{Ci→{CQi→{Ti|R}}},i=0,1,2,…,n。
框架保證了索引文件和主表在同一個Regionserver上,這樣可以保證在需要使用索引文件時只需與Region-Server建立一次連接就可以完成,提高了速度。在此架構中,用戶首先在配置文件(hbase-site.xml)中設定索引的細節(jié),主服務器從配置文件中獲取需要建立的索引信息,然后在對應的RegionServer中的IndexingCoprocessor中建立索引同時管理二級索引數(shù)據(jù)。每個節(jié)點上都部署了協(xié)處理器Coprocessor,部署之后RegionServer端中的每個區(qū)域Region 上都會自動創(chuàng)建一個區(qū)域協(xié)處理RegionCoprocessorHost實例,它的主要功能是用來維護系統(tǒng)級或表級的區(qū)域觀察者協(xié)處理RegionObserver。每當RegionObserver啟動時會將RegionCoprocessorHost初始化,初始化的過程中,RegionCoprocessorHost 會加載當前服務端所有的RegionObserver。索引管理由擴展的RegionObserver 實例(IndexRegionObserver)完成。IndexRegionObserver主要的擴展接口如表1所示。
表1 IndexRegionObserver主要擴展接口
下面以Put攔截器舉例說明索引表的更新過程:
如圖4所示,在數(shù)據(jù)表進行Put操作時,數(shù)據(jù)表會監(jiān)測插入數(shù)據(jù)的Rowkey,并由此定位到RegionServer 上的Region,該事件在Put 操作之前被CoprocessorHost攔截,并自動調(diào)用此Region 上進行監(jiān)聽的Observer 的prePut 方法。用戶可以根據(jù)自己的需求對這個方法重寫,更新索引。在索引更新完成后,即Put方法執(zhí)行完成后,Put之后的事件會再次被CoprocessorHost攔截,并調(diào)用監(jiān)聽器Observer 的postPut 方法,同樣,該方法支持用戶的重寫,以實現(xiàn)在Put 操作完成后的索引邏輯。由此可以看出,在Put操作未完成時,監(jiān)聽器將監(jiān)聽到這一事件,從而不會調(diào)用postPut 方法,索引邏輯將無法完成,保證了索引與原數(shù)據(jù)表的一致性與事件性,不會出現(xiàn)索引與原數(shù)據(jù)表無法匹配的情況。
圖4 索引表更新過程
索引的使用:在構建完索引表后,當進行索引查詢時,客戶端需要進行Scan操作,此操作將會被協(xié)處理器攔截,將檢索條件截取,并從索引表中找出符合條件的索引項,返回原數(shù)據(jù)表的Rowkey,數(shù)據(jù)表根據(jù)Rowkey查詢即可。
Coprocessor 構建的索引只是在邏輯上實現(xiàn)了索引結構,為了提高檢索Coprocessor 索引速度,需要對Coprocessor 構建的索引進行特定結構設計,內(nèi)存索引設計即可完成上述目標。內(nèi)存的索引相較于傳統(tǒng)位于磁盤的索引在設計和架構上都大不相同,基于內(nèi)存的索引在查詢效率上得到了極大提升。廣泛采用的內(nèi)存索引有T 樹、基于緩存敏感的CSS/CSB+樹和改進的Hash 索引等[13]。使用了HT 樹構建內(nèi)存索引,其結構如圖5所示。
圖5 HT樹的結構
如圖5所示,每個葉子節(jié)點有4個哈希表,每個哈希表中有3個哈希桶,在使用HT構建內(nèi)存索引時,需要通過查找算法查找到關鍵字可以插入的哈希表,然后通過計算,找到關鍵字可插入的哈希桶,判斷哈希桶是否已滿,若已滿則分裂該節(jié)點,將該關鍵字插入,若未滿則直接插入哈希桶。
內(nèi)存索引工作流程與一般索引的使用過程有所不同,具體流程如下:
(1)內(nèi)存索引初始化
當向數(shù)據(jù)表的構建過程中,需要同步進行內(nèi)存索引的建立,對外提供檢索服務。在第一次請求索引檢索時,系統(tǒng)會檢查內(nèi)存索引是否為空,如果為空,則進行索引的初始化操作,建立內(nèi)存索引。
(2)Put操作過程
Put 操作在HBase 中相當于插入操作,當HBase 執(zhí)行這個操作時,當前操作發(fā)生的Region上的Observer會攔截這個事件,向內(nèi)存索引中插入一條對應的索引項。
(3)Delete操作過程
和Put 操作相似,當客戶端執(zhí)行Delete 操作時,HBase將從表中刪除一條記錄,當前操作發(fā)生的Region上的Observer會攔截這個事件,在內(nèi)存索引中刪除一條對應的索引項。
(4)查詢操作過程
該機制中,為了提高查詢效率,盡量將數(shù)據(jù)處理過程本地化。在協(xié)處理器攔截到查詢請求后,將會構建檢索條件,根據(jù)條件在內(nèi)存索引中進行多線程檢索。得到滿足檢索條件的Rowkey 后,返回數(shù)據(jù)表中查詢原始數(shù)據(jù),將結果返回客戶端。在內(nèi)存中檢索的過程如下:
在進行內(nèi)存索引查詢時,首先在哈希表中進行查找,定位關鍵字所在桶,繼續(xù)在桶中查找,若找到,則指針指向所需記錄。當關鍵字處于內(nèi)部節(jié)點,且它的鍵為K1,K2,…,Kn。如果key <K1,則為第一個子節(jié)點;如果K1≤key <K2,則為第二個子節(jié)點。依此類推,在該子節(jié)點上遞歸運用查找過程。對于范圍查詢,在實際情況下使用頻率較高,下面給出算法進行說明。
算法1 內(nèi)存索引查找算法
輸入 查詢范圍[ks,ke]的關鍵字ks,ke。輸出 行鍵集合RQ。
RQ ←[?]// 結果集合設為空
Hs←T .Get Hash(ks)//通過樹形索引查找ks所在的哈希表
He←T .Get Hash(ke)
H ←Hs
while next[H]≠Hsdo
H ←next[H]
RQ ∪all Value[H] //將哈希表中所有值并入結果集合中
end while
for each map M in Hsdo //遍歷哈希表
if key [M]>ksthen //當遍歷映射的鍵大于范圍開始的關鍵字時
RQ ∪value[M] //將映射的值并入結果集合中
end if
end for
for each map M in Hedo if key [M]<kethen //當遍歷映射的鍵小于范圍結束的關鍵字時
RQ ∪value[M]
end if
end for
end for
(5)Region分片過程
Region分片主要為了解決在數(shù)據(jù)表數(shù)據(jù)增加時,數(shù)據(jù)行超出預設分片大小的情況。當數(shù)據(jù)表發(fā)生分片過程即Split操作時,對應的內(nèi)存索引對象也會隨之發(fā)生變化[14]。分片時,Region 將會從一個變?yōu)閮蓚€,數(shù)據(jù)表的也會一分為二,分別存于兩個Region 中,此時Observer會監(jiān)測到Split事件,通知Endpoint重新構建索引表。如圖6所示。
圖6 分片時表變化
數(shù)據(jù)表從第三項分裂成兩張表,協(xié)處理器在原索引表第一行構建索引游標,以此標記向后檢索并在Region的數(shù)據(jù)表中尋找是否有此條記錄,若存在則保留數(shù)據(jù)記錄,否則刪除,索引表由此更新完成。內(nèi)存索引構建在索引表主鍵之上,由于索引主鍵結構的改變,原索引結構需要初始化操作,即步驟一操作。新分片的內(nèi)存索引對象存儲在新的Region協(xié)處理器中。
由于內(nèi)存索引的維護都由協(xié)處理器完成,因此,內(nèi)存持久化的操作主要為了保證內(nèi)外存數(shù)據(jù)的一致性,保證主機斷電時不用重新構建索引,不涉及對索引創(chuàng)建操作。提出了內(nèi)存索引持久化方法,將建立的內(nèi)存索引從內(nèi)存中映射到外存中,用于持久化內(nèi)存索引的外存區(qū)域索引文件由存儲索引信息的索引頭和索引結構組成,索引文件與內(nèi)存空間采用內(nèi)存映射技術mmap 保持一致性[15],映射時會使用地址轉換表,將索引文件中的地址轉換為內(nèi)存中地址,并一一對應。在對內(nèi)存索引結構進行修改時,外存索引文件也會自動更新。具體的內(nèi)存持久化流程如圖7所示。
圖7 內(nèi)存持久化流程
在上述流程圖中,一個重要的步驟即如何將索引文件映射入內(nèi)存,索引文件映射入內(nèi)存后返回的是虛擬地址,索引結構數(shù)據(jù)沒有進入內(nèi)存中。為了保證索引結構完全處于內(nèi)存中,要使用相應的方法將索引結構逐步導入內(nèi)存,采用了層次遍歷的方法,將索引樹完全遍歷,所有索引結構便處于內(nèi)存中。
為評估本文提出的基于協(xié)處理器的內(nèi)存索引方案,驗證在構建二級索引時對數(shù)據(jù)庫寫入性能的影響和在構建了二級索引時對查詢性能有怎樣的提升。同時,實驗同樣基于協(xié)處理器但使用內(nèi)存構建索引(本文方案)與使用solr構建索引在查詢性能上的表現(xiàn),測試了數(shù)據(jù)擴展性與集群擴展性。本文在主機上搭建了Hadoop集群、Zookeeper集群和HBase集群,為了與同樣基于協(xié)處理器的solr 方案和HiBase 方案進行比較,還搭建了solr集群。實驗環(huán)境如表2所示。
表2 實驗環(huán)境
實驗所用數(shù)據(jù)為某河流近3 年各站點水位觀測記錄,屬性包括ID、站點(STCD)、水位(RZ)、地區(qū)(RFROM)和時間(TM),共3 000萬條數(shù)據(jù)。
實驗在分布式環(huán)境下進行,通過3臺客戶端同時向HBase 表中插入數(shù)據(jù),并在3 臺客戶端上統(tǒng)計每500 萬數(shù)據(jù)的Put 時間,為了保證實驗的準確性,進行30 次重復測試,并將結果累加求得均值。實驗分別測試了無索引、基于solr 的索引、HiBase 和本文提出的基于協(xié)處理器與內(nèi)存的索引方案在相同條件下的Put 時間,結果如圖8所示。
圖8 插入實驗結果
從實驗結果可以看出,Put 效率執(zhí)行最高的是無索引方案,這是因為在進行Put操作時,無索引方案無需分配資源進行索引的構建,而其他需構建二級索引的方案在將數(shù)據(jù)放入數(shù)據(jù)表的同時,會觸發(fā)協(xié)處理器對Put 操作進行攔截,并調(diào)用用戶自定義的方法開始構建二級索引。同時也可得出,在前對500 萬條數(shù)據(jù)進行Put 操作時,各方案的性能差距較小,但在到達1 000 萬數(shù)量級時,無索引的方案明顯優(yōu)于其他有索引方案。這是因為隨著數(shù)據(jù)量的增加,索引數(shù)據(jù)也越來越多,在進行索引插入時也會相較500 萬條記錄時更加困難。HiBase 和本方案都是基于內(nèi)存索引,在構建內(nèi)存索引時,需要在協(xié)處理器中構建適合內(nèi)存存儲的索引結構,會消耗額外的計算資源。而基于solr的方案只需要在solr中構建二級索引,不需要在程序中進行額外計算。因此,HiBase和本方案相較基于solr的方案稍有劣勢,但在一個可接受的范圍之內(nèi)。
實驗在一臺客戶端上進行,數(shù)據(jù)源仍然是3 000 萬條數(shù)據(jù),本次實驗設置了4 個測試用例。詳情如下:查詢河流站點水位值(STCD)在一定范圍內(nèi)的記錄條數(shù),對水位值范圍更改后即可得到不同的數(shù)據(jù)量。在水位值屬性上以建立HT 樹內(nèi)存索引,對水位值進行范圍查詢,圖9 所示橫坐標數(shù)據(jù)是4 次測試用例所查詢到的所有結果數(shù)據(jù)量。進行30 次測試,求得各數(shù)據(jù)庫查詢時間的平均值,結果如圖9所示。
圖9 查詢實驗結果
如圖9所示,無索引的方案與其他有索引的方案性能相比有很大差距,原因是,在原生的數(shù)據(jù)庫中搜尋一個特定值時,只能通過Scan的方式進行全表的掃描,效率極低,在數(shù)據(jù)量大時,這種查詢方式可達幾十個小時,無法進行實際使用。同時,可以發(fā)現(xiàn),無論查詢出的結果為多少,無索引的查詢速度都在110 min 左右。排除誤差影響,這是因為,無論結果如何,無索引的方案都要全表掃描,在每次掃描的數(shù)據(jù)量相同時,查詢時間變化不大。而本方案相比于同樣構建了二級索引的基于solr的方案,性能有較明顯的提升,數(shù)據(jù)量大時,查詢速度為其3.5 倍左右,與未構建索引的查詢效率相比速度是其50 倍左右,與同樣基于內(nèi)存索引的HiBase 方案提升了10%左右。本方案不僅在性能上優(yōu)勢巨大,隨著查詢結果的增大時,查詢所需的時間變化也較小,因為通過內(nèi)存進行計算,計算速度快,并且都在索引上建立了索引樹結構,在關鍵字搜索時根據(jù)樹結構搜索可以快速定位,數(shù)據(jù)量增大時,對速度影響也較小。
測試了基于協(xié)處理器的內(nèi)存索引在不同規(guī)模數(shù)據(jù)下均勻與非均勻分布數(shù)據(jù)集查詢性能。均勻分布數(shù)據(jù)集使用3 000 萬條水文數(shù)據(jù),單值查詢河流站點水位值(STCD)為62.20和范圍查詢水位值在60到65之間的記錄條數(shù),結果如圖10所示。
圖10 均勻數(shù)據(jù)集查詢性能
可以看到,當數(shù)據(jù)的規(guī)模從0 持續(xù)變化到3 000 萬級別時,查詢的時間保持了線性增長,這也驗證了基于內(nèi)存方案在數(shù)據(jù)的可擴展性方面有著良好的表現(xiàn),查詢響應時間和結果集大小成正比。因為在查詢響應時間中,主要開銷是對查詢結果集的訪問,在數(shù)據(jù)集中,數(shù)據(jù)是符合均勻分布的,隨著數(shù)據(jù)行總數(shù)的增長,查詢結果集也隨之增加,因此,查詢響應時間會與數(shù)據(jù)行總數(shù)大小成正比。
同時,本文選用了UCI數(shù)據(jù)集Abalone數(shù)據(jù)集,該數(shù)據(jù)集符合非均勻分布,數(shù)據(jù)集可分為6類,并滿足22.69%、27.53%、25.33%、19.46%、2.31%和2.68%的數(shù)據(jù)分布規(guī)律,同時長度數(shù)據(jù)也滿足非均勻分布性。為了滿足大數(shù)據(jù)測試要求,將數(shù)據(jù)量以同等倍數(shù)增加,保證數(shù)據(jù)分布的不變性,查詢數(shù)據(jù)集中Length 為130 和Length 大于110小于130的數(shù)據(jù),兩種查詢結果如圖11所示。
圖11 非均勻數(shù)據(jù)集查詢性能
由圖11 可以看出,當數(shù)據(jù)量從0 增加到600 萬時,由于數(shù)據(jù)的非均勻分布性,并未出現(xiàn)像均勻分布數(shù)據(jù)集中的線性增長趨勢。這是由于單值查詢和范圍查詢查詢的目標數(shù)值普遍分布于數(shù)據(jù)表的前半段,在查詢開始時查詢所得結果集較多,因此,查詢時間增加較快。查詢數(shù)據(jù)量增多時,滿足查詢條件的記錄條數(shù)減少,查詢增加時間也隨之變少,這也驗證了內(nèi)存索引方案良好的可擴展性。
同時,在3 000萬條數(shù)據(jù)的基礎上,通過增加節(jié)點的數(shù)量進行集群擴展性實驗,由于節(jié)點的變化對單值查詢的性能影響可以忽略。因此,實驗只對范圍查詢進行,實驗結果如圖12所示。
圖12 節(jié)點數(shù)量變化對查詢時間影響
可以看出,隨著節(jié)點數(shù)量的增加,查詢響應時間逐漸減少。在進行范圍查詢時,會向所有節(jié)點發(fā)送查詢請求,因此,當節(jié)點數(shù)量增加時,相應的查詢時間就會變短。
為了提高HBase的查詢性能,本文提出了基于協(xié)處理器Coprocessor的方案,實現(xiàn)了內(nèi)存索引的構建,并將構建的內(nèi)存索引持久化存儲在外存中,通過實驗達到了預期目標。其核心的思想為:通過協(xié)處理器構建內(nèi)存索引,具體的內(nèi)存索引結構為HT樹索引,它可以極大提高索引的檢索速度。同時,使數(shù)據(jù)表與索引文件協(xié)同分布,托管于同一臺Region Server,保證了數(shù)據(jù)表和索引文件同時分布于集群中的同一臺服務器上,在需要用到索引文件時,直接將索引文件映射入內(nèi)存,節(jié)約了時間。
但本文還有一些不足,為了查詢的簡易性,對每一個列值都創(chuàng)建了索引,這導致了構建的索引文件較為龐大,降低了索引效率。同時,在內(nèi)存中構建索引對象需要付出巨大的內(nèi)存開銷,當數(shù)量過大或索引內(nèi)容過多時,集群中各服務器的內(nèi)存會急劇消耗,有可能出現(xiàn)系統(tǒng)癱瘓。
綜上所述,本文提出的索引方案實現(xiàn)了HBase檢索速度的提高,性能和穩(wěn)定性也得到了充分的保證,但面對大數(shù)據(jù)環(huán)境下各種各樣的挑戰(zhàn),仍需要更多的努力去完善HBase的大數(shù)據(jù)處理方案。