李文武,張建鋒,王景林
(西北農(nóng)林科技大學(xué) 信息工程學(xué)院,陜西 楊凌 712100)
物聯(lián)網(wǎng)+農(nóng)業(yè)顯現(xiàn)了TB規(guī)模量的包含文本、表格、圖片等類型的KB小文件集[1]。HDFS因具備高容錯、分布式、高吞吐量的特征而被廣泛應(yīng)用于大數(shù)據(jù)的存儲[2]。但面對海量小文件,HDFS存儲大文件的結(jié)構(gòu)優(yōu)勢會被嚴重削弱,存儲效率會大打折扣[3]。其中數(shù)據(jù)塊Block(默認64 MB)作為HDFS基本存儲單元,每存入一個小文件會生成一條元數(shù)據(jù)MetaData,用于記錄其相關(guān)屬性,并存于NameNode。而一個小文件會單獨占據(jù)一個Block,且其大小遠遠小于Block體積,故會浪費大量DataNode空間資源,對應(yīng)海量MetaData也會極大增加NameNode內(nèi)存消耗[4,5]。面對來自客戶端Client頻繁的文件訪問請求,系統(tǒng)依據(jù)節(jié)點內(nèi)部索引會在多個DataNode之間“跨躍式”尋找并讀取目標文件,導(dǎo)致HDFS讀取文件花費的時間遠少于為了讀取文件所進行的RPC通信、Socket連接以及尋址等行為所花費時間,故HDFS缺少低時延訪問需求,大大降低了數(shù)據(jù)讀取效率[6,7]。
通過分析HDFS存取海量小文件時結(jié)構(gòu)設(shè)計的不足,本文提出了一種基于可擴展分布式文件系統(tǒng)EHDFS的存取方案。首先,利用空間最優(yōu)化的文件合并存儲方式,最大化提高Block空間利用。然后,改進MapFile映射結(jié)構(gòu)以建立新的文件索引模型,減少從映射文件查詢MetaData的交互步驟,以降低檢索文件時高頻的RPC通信和多次尋址帶來的時間開銷。最后,調(diào)用各存儲模塊的接口API,保證組件間的協(xié)同工作,以達到提高海量小文件的存儲效率和檢索速率的目標。
包括HDFS在內(nèi)的分布式文件系統(tǒng)對于海量小文件的存取存在的缺陷包括:DataNode空間利用、NameNode負載均衡、文件讀取速率問題。針對上述問題,國內(nèi)外存在不少企業(yè)、機構(gòu)和科研人員進行過深入研究,提出的解決方案在一定程度上緩解了小文件的存取壓力。
Apache基金會提供方案有:Hadoop Archive[8]、SequenceFile[9]和CombineFileInputFormat[10]。Hadoop Archive,通過MapReduce將多個小文件打包成一個Har文件并直接存入DataNode,方法有效減少了MetaData數(shù)量,提高了NameNode內(nèi)存利用率,但存在源文件需手動刪除和Har文件具有特定格式且創(chuàng)建后無法修改的弊端[11]。SequenceFile,通過將小文件名作為key、內(nèi)容作為value,以二進制形式進行合并存儲。由于缺少建立文件索引而具有較大局限性,對于文件檢索需要遍歷整個文件集,故不適合數(shù)據(jù)的隨機訪問[12]。CombineFileInput-Format,通過將多個小文件打包至一個split,每個Mapper處理多個split,降低了Mapper處理的數(shù)據(jù)量與數(shù)據(jù)塊大小的耦合關(guān)系。方案存在較差的小文件寫的性能表現(xiàn),故只適合小文件已上傳至集群的分布式計算[13]。
Zhou W等針對小文件存儲性能低下提出了一種利用非阻塞I/O存儲方式進行小文件歸并的獨立引擎管理方法。該方法能夠?qū)ψx取次數(shù)最少的文件進行分開并分組,但在數(shù)據(jù)塊批處理生成過程中會產(chǎn)生大量元數(shù)據(jù)的問題[14]。the New Hadoop Archive(NHAR),一種基于現(xiàn)存HAR歸檔文件上進行小文件壓縮的存儲方式。該方法是通過消耗大量內(nèi)存進行小文件的追加工作,而且易導(dǎo)致壓縮策略發(fā)生故障而達不到節(jié)省空間的效果[15]。Karan A等針對由海量小文件存取造成NameNode瓶頸問題提出了一種優(yōu)化主節(jié)點工作方式的方法,通過將小文件與其對應(yīng)生成的元數(shù)據(jù)進行共同存儲進行元數(shù)據(jù)管理。由于方案缺少對大量小文件的緩存進行處理的考慮,故存儲效率提升較小[16]。Anitha.R等基于HDFS增加了少數(shù)模塊,提出了可擴展分布式文件系統(tǒng)EHDFS(extend hadoop distributed files system)。EHDFS通過合并操作減少文件數(shù)量,同時為合并文件建立有效索引機制,隨后通過預(yù)取緩存模塊提高數(shù)據(jù)訪問速率[17]。方案有效減少了元數(shù)據(jù)數(shù)量,降低了NameNode內(nèi)存消耗,縮短了文件訪問時間,對文件系統(tǒng)的改進具有借鑒意義。
針對HDFS存儲海量小文件效率低下的問題,本文采用可擴展分布式文件系統(tǒng)EHDFS的結(jié)構(gòu)模型,從存儲與檢索方面提出一種改進方案。方案整體模型架構(gòu)如圖1所示。存取方案核心模塊包括:基于最優(yōu)化策略的小文件合并存儲單元、基于MapFile方法的小文件索引單元。方案是對HDFS結(jié)構(gòu)形態(tài)的補充,憑借客戶端、核心模塊與HDFS集群間的相互作用,有助于文件的可靠交互與自由存取。
圖1 方案整體模型架構(gòu)
構(gòu)建存儲與索引模型是方案的核心成分,承擔(dān)著相鄰階段的確切職責(zé)。文件存儲階段,為了充分利用DataNode空間資源,降低因海量MetaData所帶來的NameNode內(nèi)存壓力,將使用最優(yōu)化策略改進小文件的合并方式,使其盡可能地填滿且均勻分布在數(shù)據(jù)塊中。文件檢索階段,建立高效的映射結(jié)構(gòu)和文件索引是進行快速、準確檢索文件的關(guān)鍵,通過改進MapFile索引算法的映射關(guān)系結(jié)構(gòu)、索引存儲位置和組成元素以建立新的兩級索引模型,從而減少在MapFile文件中查詢目標文件因缺乏構(gòu)建全體小文件的索引而無法滿足隨機訪問的需求,降低分散索引與跨越式搜索目標文件所消耗的額外時長。
合并是存儲海量小文件的有效手段,它能減少DataNode空間浪費和NameNode內(nèi)存負載。所以,關(guān)鍵在于如何構(gòu)建有效的合并算法模型。本文做法是通過引入最優(yōu)化策略[18]以構(gòu)建新的合并算法,整體合并存儲流程如圖2所示。核心思想為:充分考慮待合并文件體積差異和分布狀態(tài)對數(shù)據(jù)塊Block空間占用的差異性影響,憑借閾值判別分析,讓小文件均勻分布于Block中,使合并文件盡可能接近數(shù)據(jù)塊閾值,做到節(jié)點空間的最大化利用。合并算法定義3種數(shù)據(jù)結(jié)構(gòu):合并隊列mergeQ、備用隊列backupQ和臨時隊列tempQ。mergeQ用于加載與合并閾值相符合的小文件;backupQ是相對于mergeQ的備用隊列,兩種隊列可相互轉(zhuǎn)化,以提供小文件多次合并的可能;tempQ用于暫時存儲不符合合并條件的小文件。合并算法中,合并閾值與3種隊列的初始化大小定義為Block_size。mergeQ數(shù)量a使用待上傳文件總體積與Block_size比值,backupQ和tempQ數(shù)量b、c遠遠小于a。另外,合并算法聲明:為了避免各種異常影響合并隊列較長時間接收不到小文件而持續(xù)占用系統(tǒng)資源,合并存儲的執(zhí)行過程規(guī)定在合理有效的時間T內(nèi)進行,時間T依據(jù)實際上傳的數(shù)據(jù)規(guī)模量進行設(shè)置。
圖2 最優(yōu)化合并存儲流程
2.1.1 最優(yōu)化合并存儲步驟
步驟1 時間T內(nèi)依次遍歷待上傳存儲的文件集,若當(dāng)前上傳文件體積f_size大于2/3倍數(shù)據(jù)塊閾值Block_size,則直接存儲至HDFS,繼續(xù)遍歷剩余文件;否則轉(zhuǎn)跳至步驟2。
步驟2 依據(jù)用戶準備上傳的文件總體積與合并閾值,預(yù)先計算合并隊列mergeQ的數(shù)量a,備用隊列backupQ和臨時隊列tempQ的數(shù)量b和c遠遠小于a,依據(jù)實際取用合并隊列a的1/10,不足向上取整。然后按需依次初始化對應(yīng)的3種隊列。
步驟3 若當(dāng)前文件大小f_size大于小文件閾值f_smallsize,則將該文件添加至空的合并隊列mergeQ,繼續(xù)遍歷剩余文件;若f_size不大于f_smallsize,則將該文件放至臨時隊列tempQ,然后轉(zhuǎn)跳到步驟4。
步驟4 從臨時隊列tempQ中選取體積最小的文件f_sizemin和當(dāng)前剩余空間最小的合并隊列mergeQ_leftsizemin。
步驟5 比較f_sizemin與mergeQ_leftsizemin的體積大小,若f_sizemin大于mergeQ_leftsizemin,則說明當(dāng)前所有合并隊列都無法容納該文件,此時將該文件添加至空的備用隊列backupQ,并轉(zhuǎn)換成新的合并隊列mergeQ,然后繼續(xù)新一輪的合并操作;若f_sizemin小于等于mergeQ_leftsizemin,則將該文件添加至該合并隊列,然后轉(zhuǎn)跳到步驟6。
步驟6 計算當(dāng)前合并隊列mergeQ的文件占用總體積,若總體積大于等于數(shù)據(jù)塊閾值,則將該合并隊列mergeQ中的全體文件打包存儲至HDFS集群節(jié)點的數(shù)據(jù)塊Block中,然后銷毀該mergeQ;否則繼續(xù)新一輪的合并操作。
2.1.2 合并算法執(zhí)行效果對比
通用合并策略在文件遍歷的進程中,因為缺乏考慮體積差異的小文件存儲于同一數(shù)據(jù)塊所占空間對對方和剩余空間的影響,易造成文件溢出、分割與非均衡存儲,算法執(zhí)行效果如圖3所示。而使用改進合并策略對相同文件的執(zhí)行效果如圖4所示,較為改善之處在于算法能夠記錄每一次合并對塊空間的占用情況,并動態(tài)判斷與調(diào)整最適合該塊合并的目標文件,因此會較大節(jié)省數(shù)據(jù)塊的消耗,提高現(xiàn)存塊空間的利用。
圖3 通用合并算法效果
圖4 最優(yōu)化合并算法效果
2.1.3 最優(yōu)化合并存儲關(guān)鍵算法
Input: 農(nóng)業(yè)小文件集{ A }
Output: 合并成功”Success”或者失敗”Failure”
WHILE uploadTime < T
/*整個合并存儲在有效時間T內(nèi)進行*/
THEN Traverse uploadfiles;
/*依次遍歷文件*/
IF Next file_size > 2/3Block_size
/*文件預(yù)處理,排除大文件對合并算法的干擾*/
THEN Write To HDFS;
ELSE
/*按需初始化3種結(jié)構(gòu)隊列,開始文件合并流程*/
Initialize mergeQ;
Initialize backupQ;
Initialize tempQ;
END IF
IF file_size > file_smallsize
/*判斷當(dāng)前合并文件大小,決策文件執(zhí)行流程*/
THEN Add To mergeQ;
Traverse uploadfiles;
ELSE
Add To tempQ;
END IF
THEN
/*選取合適的小文件與合并隊列進行組合, 實現(xiàn)不同大小的文件進行均勻搭配歸并, 最大化填滿數(shù)據(jù)塊*/
Search file_sizemin In tempQ;
Search mergeQ_leftsizemin In All mergeQ;
IF file_sizemin > mergeQ_leftsizemin
THEN Add To backupQ;
Convert backupQ Into mergeQ;
/*轉(zhuǎn)換隊列角色, 以提供之前未滿足合并條件的文件進行多次合并的可能*/
Traverse uploadfiles;
ELSE
Add To mergeQ;
END IF
IF mergeQ_occupysize > Block_size
/*合并完成條件判斷, 整體歸并存儲節(jié)點數(shù)據(jù)塊*/
THEN Write To HDFS;
System Reclaim mergeQ;
/*系統(tǒng)回收隊列占用資源*/
ELSE
Traverse uploadfiles;
END IF
END WHILE
MapFile映射文件技術(shù)[19]是對SequenceFile序列文件技術(shù)的改進方案,有效克服了序列文件缺乏文件映射關(guān)系需要遍歷整個文件序列的缺陷。其中由
為了減少文件索引的交互時長,提高海量數(shù)據(jù)的檢索速率,本文將對MapFile索引結(jié)構(gòu)做出改進以建立新的文件索引策略。主要思想是:調(diào)整文件映射關(guān)系結(jié)構(gòu)、優(yōu)化索引文件組成元素以及更改索引文件存儲位置。首先,應(yīng)避免跨度較大的多層級映射結(jié)構(gòu),此處采用線性結(jié)構(gòu)
表1 映射關(guān)系結(jié)構(gòu)
最后通過解析小文件對應(yīng)MetaData的屬性元素,利用MapReduce并行計算引擎按映射結(jié)構(gòu)建立全局小文件索引,獨立保存至Hbase數(shù)據(jù)庫。索引建立過程依賴于Map函數(shù)與Reduce函數(shù),一個Map函數(shù)負責(zé)一個數(shù)據(jù)塊中的合并文件,一個Reduce函數(shù)負責(zé)根據(jù)文件屬性歸納每個Map函數(shù)生成的索引,進而創(chuàng)建全局的文件索引。其中MapReduce索引生成原理如圖5所示。采用索引與文件分離存儲的方式,能避免聚合存儲產(chǎn)生的紊亂。
索引構(gòu)建階段,相比較存在低擴展性與低容錯性、存儲模式單一等局限的關(guān)系型數(shù)據(jù)庫RDBMS,具備非結(jié)構(gòu)化存儲模式、高并發(fā)讀寫與隨機查詢、按列存儲且同列數(shù)據(jù)的類型與特征擁有高相似度等優(yōu)勢的非關(guān)系型數(shù)據(jù)庫HBase[21],能夠更加靈活地滿足海量多結(jié)構(gòu)農(nóng)業(yè)小文件的索引存儲需求。Hbase數(shù)據(jù)結(jié)構(gòu)模型由主鍵Row Key、列族Column Family、列限定符Column Qualifier、時間戳Time Stamp主要元素組成。其中Row Key用于唯一標識一行記錄,同時作為文件檢索的唯一索引標識[22]。本文存儲于Hbase數(shù)據(jù)庫的文件索引數(shù)據(jù)表見表2。
圖5 MapReduce索引生成
表2 Hbase文件索引數(shù)據(jù)
由于索引文件置于Hbase組件,位于HDFS外部,相比直接節(jié)點內(nèi)部的查找步驟會稍有增加。但索引本身采用多標識的線性結(jié)構(gòu),能夠避免跨越式檢索而實現(xiàn)集中位置匹配,并且相當(dāng)程度減輕了NameNode對海量元數(shù)據(jù)信息的管理壓力,增強其對文件檢索的控制力。當(dāng)面對來自客戶端的訪問請求時,系統(tǒng)文件檢索流程如圖6所示。面對Client的文件讀取請求,EHDFS存取模型系統(tǒng)的文件檢索步驟具體如下:
步驟1 HDFS客戶端發(fā)起文件讀取的請求,包括文件基本屬性。系統(tǒng)預(yù)判讀取文件的存在性,若不存在,直接反饋給Client錯誤輸入;否則轉(zhuǎn)至步驟2。
步驟2 系統(tǒng)按規(guī)則預(yù)判讀取文件的大小性,若為大文件,系統(tǒng)直接前往NameNode依據(jù)元數(shù)據(jù)信息確定文件所在Block位置,然后前往目的存儲區(qū)域并將查詢結(jié)果反饋至Client;否則轉(zhuǎn)至步驟3。
步驟3 確定為小文件后,系統(tǒng)會前往Hbase數(shù)據(jù)庫,依據(jù)索引數(shù)據(jù)表的映射關(guān)系,通過相關(guān)文件屬性獲取目標小文件存儲地址,然后前往目標文件位置并將查詢結(jié)果反饋至Client。
圖6 文件檢索結(jié)構(gòu)
為了驗證本文方案在數(shù)據(jù)存儲與檢索層面的可行性,實驗將使用學(xué)校大數(shù)據(jù)實驗室的4臺計算機組建完全分布式的集群測試環(huán)境,其中NameNode作為主控節(jié)點使用1臺計算機,DataNode作為存儲節(jié)點使用3臺計算機,各個節(jié)點服務(wù)器軟硬件參數(shù)完全一致,以保證測試環(huán)境的高度統(tǒng)一,節(jié)點服務(wù)器配置信息見表3。
表3 節(jié)點服務(wù)器配置信息
依據(jù)研究內(nèi)容,實驗將選取NameNode內(nèi)存占用、數(shù)據(jù)讀取時長作為測試指標來驗證方案的整體數(shù)據(jù)存取效率。NameNode內(nèi)存消耗用于驗證最優(yōu)化合并策略的有效性,數(shù)據(jù)讀取速率是對新的文件索引模型可行性的驗證,通過測試在不同指標下的表現(xiàn)狀態(tài)以確定改進方案的總體優(yōu)劣情況。
實驗擬使用國家農(nóng)業(yè)科學(xué)數(shù)據(jù)中心平臺共享的農(nóng)業(yè)資源與環(huán)境科學(xué)數(shù)據(jù)進行方案驗證。測試數(shù)據(jù)采用75 000條由溫度、濕度、降雨量、天氣值等類別組成的約15.1 GB文件集構(gòu)成,具體文件的組成數(shù)量與總體占比如圖7所示。圖表清晰展示了數(shù)據(jù)集中不同大小文件所占數(shù)量的分布狀態(tài),其中2 M以內(nèi)文件占據(jù)90%以上,該數(shù)據(jù)既能切入海量小文件對HDFS存取效率低下的研究要點,又能充分體現(xiàn)農(nóng)業(yè)環(huán)境科學(xué)數(shù)據(jù)小的特征。為了驗證系統(tǒng)在不同數(shù)據(jù)容量下的有效性,實驗將數(shù)據(jù)劃分為15 000,30 000,50 000,75 000進行分組測試。為了突出本方案與MapFile、標準HDFS的性能差異性,實驗將設(shè)置對照組加以區(qū)分不同方法對數(shù)據(jù)處理的優(yōu)劣狀態(tài)。為了提高測試結(jié)果的精確性,實驗將對每份指標進行5組重復(fù)實驗,然后取其平均值作為測試結(jié)果。
圖7 數(shù)據(jù)集類別組成
3.2.1 NameNode內(nèi)存占用測試
分析NameNode內(nèi)存占用是驗證最優(yōu)化合并策略下節(jié)點空間是否充分合理化使用的直觀方式。實驗將采用控制變量法分別對標準HDFS、MapFile與本文方案進行數(shù)據(jù)上傳存儲的對照測試,每組實驗在保持單一變量環(huán)境下,重復(fù)5次測試取其平均值,以確定3種方案在4組不同數(shù)據(jù)量的存儲壓力下NameNode內(nèi)存占用率的差異化表現(xiàn),實驗結(jié)果如圖8所示。
圖8 NameNode內(nèi)存占用
依據(jù)實驗結(jié)果,標準HDFS因缺乏文件合并預(yù)處理,對應(yīng)產(chǎn)生大量MetaData導(dǎo)致NameNode內(nèi)存消耗較大,整體表現(xiàn)不佳。MapFile與本文方案相對表現(xiàn)良好,尤其體現(xiàn)在數(shù)據(jù)量較大狀態(tài),且本方案要稍微優(yōu)于MapFile,因為通過最優(yōu)化合并策略能夠考慮到體積和分布狀態(tài)各異的小文件對數(shù)據(jù)塊占用的影響,進而提高文件合并的機率,從而減少MetaData數(shù)量以節(jié)省NameNode內(nèi)存空間。
3.2.2 數(shù)據(jù)讀取時長測試
數(shù)據(jù)讀取時長能夠直觀反映文件索引結(jié)構(gòu)是否有效提高文件系統(tǒng)的檢索效率。實驗將在數(shù)據(jù)分組存儲的NameNode內(nèi)存占用的階段性實驗基礎(chǔ)上進行。實驗分別對標準HDFS、MapFile與本文方案進行文件的隨機檢索。為避免多環(huán)境因素的干擾,每組測試均保持單一環(huán)境變量,利用隨機函數(shù)選取各組樣本的1000條文件進行檢索,以測試方案在不同樣本容量下的文件讀取效率,然后統(tǒng)計5次重復(fù)實驗的平均讀取時長,實驗結(jié)果如圖9所示。
圖9 隨機文件平均讀取時長
依據(jù)實驗結(jié)果,標準HDFS因索引結(jié)構(gòu)設(shè)計因素使得文件檢索節(jié)點通信時間過長,導(dǎo)致缺少低時延的訪問需求,整體表現(xiàn)一般。MapFile與本文方案優(yōu)化了文件索引結(jié)構(gòu),整體表現(xiàn)較好。伴隨數(shù)據(jù)量的增長,本文方案優(yōu)勢凸顯,因為新的文件索引結(jié)構(gòu)能夠考慮到節(jié)點間的數(shù)據(jù)交互影響與Hbase數(shù)據(jù)表的結(jié)構(gòu)優(yōu)勢,有效縮短交互時長以提升訪問速率。
面對HDFS存取海量小文件低效問題,本文通過分析當(dāng)前各解決方案的優(yōu)劣,研究HDFS結(jié)構(gòu)設(shè)計對農(nóng)業(yè)小文件存取的利弊,針對DataNode空間浪費過大,NameNode內(nèi)存占用過高,以及文件索引交互時長過多,從存儲與檢索層面構(gòu)建了一種基于可擴展分布式文件系統(tǒng)EHDFS架構(gòu)的解決方案。實驗結(jié)果表明,在數(shù)據(jù)存儲階段,方案通過最優(yōu)化文件合并的存儲方式,有效提高了DataNode空間利用,并降低了NameNode內(nèi)存占用。在數(shù)據(jù)檢索階段,通過改進文件的索引結(jié)構(gòu)設(shè)計,有效節(jié)省了數(shù)據(jù)檢索的節(jié)點交互時長。所以方案整體上能夠滿足HDFS分布式存取海量農(nóng)業(yè)小文件的需要。但是與MapFile比較,本方案提升有限,仍然具有較大改進空間。