李文武,張建鋒,王景林
(西北農林科技大學 信息工程學院,陜西 楊凌 712100)
物聯網+農業顯現了TB規模量的包含文本、表格、圖片等類型的KB小文件集[1]。HDFS因具備高容錯、分布式、高吞吐量的特征而被廣泛應用于大數據的存儲[2]。但面對海量小文件,HDFS存儲大文件的結構優勢會被嚴重削弱,存儲效率會大打折扣[3]。其中數據塊Block(默認64 MB)作為HDFS基本存儲單元,每存入一個小文件會生成一條元數據MetaData,用于記錄其相關屬性,并存于NameNode。而一個小文件會單獨占據一個Block,且其大小遠遠小于Block體積,故會浪費大量DataNode空間資源,對應海量MetaData也會極大增加NameNode內存消耗[4,5]。面對來自客戶端Client頻繁的文件訪問請求,系統依據節點內部索引會在多個DataNode之間“跨躍式”尋找并讀取目標文件,導致HDFS讀取文件花費的時間遠少于為了讀取文件所進行的RPC通信、Socket連接以及尋址等行為所花費時間,故HDFS缺少低時延訪問需求,大大降低了數據讀取效率[6,7]。
通過分析HDFS存取海量小文件時結構設計的不足,本文提出了一種基于可擴展分布式文件系統EHDFS的存取方案。首先,利用空間最優化的文件合并存儲方式,最大化提高Block空間利用。然后,改進MapFile映射結構以建立新的文件索引模型,減少從映射文件查詢MetaData的交互步驟,以降低檢索文件時高頻的RPC通信和多次尋址帶來的時間開銷。最后,調用各存儲模塊的接口API,保證組件間的協同工作,以達到提高海量小文件的存儲效率和檢索速率的目標。
包括HDFS在內的分布式文件系統對于海量小文件的存取存在的缺陷包括:DataNode空間利用、NameNode負載均衡、文件讀取速率問題。針對上述問題,國內外存在不少企業、機構和科研人員進行過深入研究,提出的解決方案在一定程度上緩解了小文件的存取壓力。
Apache基金會提供方案有:Hadoop Archive[8]、SequenceFile[9]和CombineFileInputFormat[10]。Hadoop Archive,通過MapReduce將多個小文件打包成一個Har文件并直接存入DataNode,方法有效減少了MetaData數量,提高了NameNode內存利用率,但存在源文件需手動刪除和Har文件具有特定格式且創建后無法修改的弊端[11]。SequenceFile,通過將小文件名作為key、內容作為value,以二進制形式進行合并存儲。由于缺少建立文件索引而具有較大局限性,對于文件檢索需要遍歷整個文件集,故不適合數據的隨機訪問[12]。CombineFileInput-Format,通過將多個小文件打包至一個split,每個Mapper處理多個split,降低了Mapper處理的數據量與數據塊大小的耦合關系。方案存在較差的小文件寫的性能表現,故只適合小文件已上傳至集群的分布式計算[13]。
Zhou W等針對小文件存儲性能低下提出了一種利用非阻塞I/O存儲方式進行小文件歸并的獨立引擎管理方法。該方法能夠對讀取次數最少的文件進行分開并分組,但在數據塊批處理生成過程中會產生大量元數據的問題[14]。the New Hadoop Archive(NHAR),一種基于現存HAR歸檔文件上進行小文件壓縮的存儲方式。該方法是通過消耗大量內存進行小文件的追加工作,而且易導致壓縮策略發生故障而達不到節省空間的效果[15]。Karan A等針對由海量小文件存取造成NameNode瓶頸問題提出了一種優化主節點工作方式的方法,通過將小文件與其對應生成的元數據進行共同存儲進行元數據管理。由于方案缺少對大量小文件的緩存進行處理的考慮,故存儲效率提升較小[16]。Anitha.R等基于HDFS增加了少數模塊,提出了可擴展分布式文件系統EHDFS(extend hadoop distributed files system)。EHDFS通過合并操作減少文件數量,同時為合并文件建立有效索引機制,隨后通過預取緩存模塊提高數據訪問速率[17]。方案有效減少了元數據數量,降低了NameNode內存消耗,縮短了文件訪問時間,對文件系統的改進具有借鑒意義。
針對HDFS存儲海量小文件效率低下的問題,本文采用可擴展分布式文件系統EHDFS的結構模型,從存儲與檢索方面提出一種改進方案。方案整體模型架構如圖1所示。存取方案核心模塊包括:基于最優化策略的小文件合并存儲單元、基于MapFile方法的小文件索引單元。方案是對HDFS結構形態的補充,憑借客戶端、核心模塊與HDFS集群間的相互作用,有助于文件的可靠交互與自由存取。

圖1 方案整體模型架構
構建存儲與索引模型是方案的核心成分,承擔著相鄰階段的確切職責。文件存儲階段,為了充分利用DataNode空間資源,降低因海量MetaData所帶來的NameNode內存壓力,將使用最優化策略改進小文件的合并方式,使其盡可能地填滿且均勻分布在數據塊中。文件檢索階段,建立高效的映射結構和文件索引是進行快速、準確檢索文件的關鍵,通過改進MapFile索引算法的映射關系結構、索引存儲位置和組成元素以建立新的兩級索引模型,從而減少在MapFile文件中查詢目標文件因缺乏構建全體小文件的索引而無法滿足隨機訪問的需求,降低分散索引與跨越式搜索目標文件所消耗的額外時長。
合并是存儲海量小文件的有效手段,它能減少DataNode空間浪費和NameNode內存負載。所以,關鍵在于如何構建有效的合并算法模型。本文做法是通過引入最優化策略[18]以構建新的合并算法,整體合并存儲流程如圖2所示。核心思想為:充分考慮待合并文件體積差異和分布狀態對數據塊Block空間占用的差異性影響,憑借閾值判別分析,讓小文件均勻分布于Block中,使合并文件盡可能接近數據塊閾值,做到節點空間的最大化利用。合并算法定義3種數據結構:合并隊列mergeQ、備用隊列backupQ和臨時隊列tempQ。mergeQ用于加載與合并閾值相符合的小文件;backupQ是相對于mergeQ的備用隊列,兩種隊列可相互轉化,以提供小文件多次合并的可能;tempQ用于暫時存儲不符合合并條件的小文件。合并算法中,合并閾值與3種隊列的初始化大小定義為Block_size。mergeQ數量a使用待上傳文件總體積與Block_size比值,backupQ和tempQ數量b、c遠遠小于a。另外,合并算法聲明:為了避免各種異常影響合并隊列較長時間接收不到小文件而持續占用系統資源,合并存儲的執行過程規定在合理有效的時間T內進行,時間T依據實際上傳的數據規模量進行設置。

圖2 最優化合并存儲流程
2.1.1 最優化合并存儲步驟
步驟1 時間T內依次遍歷待上傳存儲的文件集,若當前上傳文件體積f_size大于2/3倍數據塊閾值Block_size,則直接存儲至HDFS,繼續遍歷剩余文件;否則轉跳至步驟2。
步驟2 依據用戶準備上傳的文件總體積與合并閾值,預先計算合并隊列mergeQ的數量a,備用隊列backupQ和臨時隊列tempQ的數量b和c遠遠小于a,依據實際取用合并隊列a的1/10,不足向上取整。然后按需依次初始化對應的3種隊列。
步驟3 若當前文件大小f_size大于小文件閾值f_smallsize,則將該文件添加至空的合并隊列mergeQ,繼續遍歷剩余文件;若f_size不大于f_smallsize,則將該文件放至臨時隊列tempQ,然后轉跳到步驟4。
步驟4 從臨時隊列tempQ中選取體積最小的文件f_sizemin和當前剩余空間最小的合并隊列mergeQ_leftsizemin。
步驟5 比較f_sizemin與mergeQ_leftsizemin的體積大小,若f_sizemin大于mergeQ_leftsizemin,則說明當前所有合并隊列都無法容納該文件,此時將該文件添加至空的備用隊列backupQ,并轉換成新的合并隊列mergeQ,然后繼續新一輪的合并操作;若f_sizemin小于等于mergeQ_leftsizemin,則將該文件添加至該合并隊列,然后轉跳到步驟6。
步驟6 計算當前合并隊列mergeQ的文件占用總體積,若總體積大于等于數據塊閾值,則將該合并隊列mergeQ中的全體文件打包存儲至HDFS集群節點的數據塊Block中,然后銷毀該mergeQ;否則繼續新一輪的合并操作。
2.1.2 合并算法執行效果對比
通用合并策略在文件遍歷的進程中,因為缺乏考慮體積差異的小文件存儲于同一數據塊所占空間對對方和剩余空間的影響,易造成文件溢出、分割與非均衡存儲,算法執行效果如圖3所示。而使用改進合并策略對相同文件的執行效果如圖4所示,較為改善之處在于算法能夠記錄每一次合并對塊空間的占用情況,并動態判斷與調整最適合該塊合并的目標文件,因此會較大節省數據塊的消耗,提高現存塊空間的利用。

圖3 通用合并算法效果

圖4 最優化合并算法效果
2.1.3 最優化合并存儲關鍵算法
Input: 農業小文件集{ A }
Output: 合并成功”Success”或者失敗”Failure”
WHILE uploadTime < T
/*整個合并存儲在有效時間T內進行*/
THEN Traverse uploadfiles;
/*依次遍歷文件*/
IF Next file_size > 2/3Block_size
/*文件預處理,排除大文件對合并算法的干擾*/
THEN Write To HDFS;
ELSE
/*按需初始化3種結構隊列,開始文件合并流程*/
Initialize mergeQ;
Initialize backupQ;
Initialize tempQ;
END IF
IF file_size > file_smallsize
/*判斷當前合并文件大小,決策文件執行流程*/
THEN Add To mergeQ;
Traverse uploadfiles;
ELSE
Add To tempQ;
END IF
THEN
/*選取合適的小文件與合并隊列進行組合, 實現不同大小的文件進行均勻搭配歸并, 最大化填滿數據塊*/
Search file_sizemin In tempQ;
Search mergeQ_leftsizemin In All mergeQ;
IF file_sizemin > mergeQ_leftsizemin
THEN Add To backupQ;
Convert backupQ Into mergeQ;
/*轉換隊列角色, 以提供之前未滿足合并條件的文件進行多次合并的可能*/
Traverse uploadfiles;
ELSE
Add To mergeQ;
END IF
IF mergeQ_occupysize > Block_size
/*合并完成條件判斷, 整體歸并存儲節點數據塊*/
THEN Write To HDFS;
System Reclaim mergeQ;
/*系統回收隊列占用資源*/
ELSE
Traverse uploadfiles;
END IF
END WHILE
MapFile映射文件技術[19]是對SequenceFile序列文件技術的改進方案,有效克服了序列文件缺乏文件映射關系需要遍歷整個文件序列的缺陷。其中由
為了減少文件索引的交互時長,提高海量數據的檢索速率,本文將對MapFile索引結構做出改進以建立新的文件索引策略。主要思想是:調整文件映射關系結構、優化索引文件組成元素以及更改索引文件存儲位置。首先,應避免跨度較大的多層級映射結構,此處采用線性結構

表1 映射關系結構
最后通過解析小文件對應MetaData的屬性元素,利用MapReduce并行計算引擎按映射結構建立全局小文件索引,獨立保存至Hbase數據庫。索引建立過程依賴于Map函數與Reduce函數,一個Map函數負責一個數據塊中的合并文件,一個Reduce函數負責根據文件屬性歸納每個Map函數生成的索引,進而創建全局的文件索引。其中MapReduce索引生成原理如圖5所示。采用索引與文件分離存儲的方式,能避免聚合存儲產生的紊亂。
索引構建階段,相比較存在低擴展性與低容錯性、存儲模式單一等局限的關系型數據庫RDBMS,具備非結構化存儲模式、高并發讀寫與隨機查詢、按列存儲且同列數據的類型與特征擁有高相似度等優勢的非關系型數據庫HBase[21],能夠更加靈活地滿足海量多結構農業小文件的索引存儲需求。Hbase數據結構模型由主鍵Row Key、列族Column Family、列限定符Column Qualifier、時間戳Time Stamp主要元素組成。其中Row Key用于唯一標識一行記錄,同時作為文件檢索的唯一索引標識[22]。本文存儲于Hbase數據庫的文件索引數據表見表2。

圖5 MapReduce索引生成

表2 Hbase文件索引數據
由于索引文件置于Hbase組件,位于HDFS外部,相比直接節點內部的查找步驟會稍有增加。但索引本身采用多標識的線性結構,能夠避免跨越式檢索而實現集中位置匹配,并且相當程度減輕了NameNode對海量元數據信息的管理壓力,增強其對文件檢索的控制力。當面對來自客戶端的訪問請求時,系統文件檢索流程如圖6所示。面對Client的文件讀取請求,EHDFS存取模型系統的文件檢索步驟具體如下:
步驟1 HDFS客戶端發起文件讀取的請求,包括文件基本屬性。系統預判讀取文件的存在性,若不存在,直接反饋給Client錯誤輸入;否則轉至步驟2。
步驟2 系統按規則預判讀取文件的大小性,若為大文件,系統直接前往NameNode依據元數據信息確定文件所在Block位置,然后前往目的存儲區域并將查詢結果反饋至Client;否則轉至步驟3。
步驟3 確定為小文件后,系統會前往Hbase數據庫,依據索引數據表的映射關系,通過相關文件屬性獲取目標小文件存儲地址,然后前往目標文件位置并將查詢結果反饋至Client。

圖6 文件檢索結構
為了驗證本文方案在數據存儲與檢索層面的可行性,實驗將使用學校大數據實驗室的4臺計算機組建完全分布式的集群測試環境,其中NameNode作為主控節點使用1臺計算機,DataNode作為存儲節點使用3臺計算機,各個節點服務器軟硬件參數完全一致,以保證測試環境的高度統一,節點服務器配置信息見表3。

表3 節點服務器配置信息
依據研究內容,實驗將選取NameNode內存占用、數據讀取時長作為測試指標來驗證方案的整體數據存取效率。NameNode內存消耗用于驗證最優化合并策略的有效性,數據讀取速率是對新的文件索引模型可行性的驗證,通過測試在不同指標下的表現狀態以確定改進方案的總體優劣情況。
實驗擬使用國家農業科學數據中心平臺共享的農業資源與環境科學數據進行方案驗證。測試數據采用75 000條由溫度、濕度、降雨量、天氣值等類別組成的約15.1 GB文件集構成,具體文件的組成數量與總體占比如圖7所示。圖表清晰展示了數據集中不同大小文件所占數量的分布狀態,其中2 M以內文件占據90%以上,該數據既能切入海量小文件對HDFS存取效率低下的研究要點,又能充分體現農業環境科學數據小的特征。為了驗證系統在不同數據容量下的有效性,實驗將數據劃分為15 000,30 000,50 000,75 000進行分組測試。為了突出本方案與MapFile、標準HDFS的性能差異性,實驗將設置對照組加以區分不同方法對數據處理的優劣狀態。為了提高測試結果的精確性,實驗將對每份指標進行5組重復實驗,然后取其平均值作為測試結果。

圖7 數據集類別組成
3.2.1 NameNode內存占用測試
分析NameNode內存占用是驗證最優化合并策略下節點空間是否充分合理化使用的直觀方式。實驗將采用控制變量法分別對標準HDFS、MapFile與本文方案進行數據上傳存儲的對照測試,每組實驗在保持單一變量環境下,重復5次測試取其平均值,以確定3種方案在4組不同數據量的存儲壓力下NameNode內存占用率的差異化表現,實驗結果如圖8所示。

圖8 NameNode內存占用
依據實驗結果,標準HDFS因缺乏文件合并預處理,對應產生大量MetaData導致NameNode內存消耗較大,整體表現不佳。MapFile與本文方案相對表現良好,尤其體現在數據量較大狀態,且本方案要稍微優于MapFile,因為通過最優化合并策略能夠考慮到體積和分布狀態各異的小文件對數據塊占用的影響,進而提高文件合并的機率,從而減少MetaData數量以節省NameNode內存空間。
3.2.2 數據讀取時長測試
數據讀取時長能夠直觀反映文件索引結構是否有效提高文件系統的檢索效率。實驗將在數據分組存儲的NameNode內存占用的階段性實驗基礎上進行。實驗分別對標準HDFS、MapFile與本文方案進行文件的隨機檢索。為避免多環境因素的干擾,每組測試均保持單一環境變量,利用隨機函數選取各組樣本的1000條文件進行檢索,以測試方案在不同樣本容量下的文件讀取效率,然后統計5次重復實驗的平均讀取時長,實驗結果如圖9所示。

圖9 隨機文件平均讀取時長
依據實驗結果,標準HDFS因索引結構設計因素使得文件檢索節點通信時間過長,導致缺少低時延的訪問需求,整體表現一般。MapFile與本文方案優化了文件索引結構,整體表現較好。伴隨數據量的增長,本文方案優勢凸顯,因為新的文件索引結構能夠考慮到節點間的數據交互影響與Hbase數據表的結構優勢,有效縮短交互時長以提升訪問速率。
面對HDFS存取海量小文件低效問題,本文通過分析當前各解決方案的優劣,研究HDFS結構設計對農業小文件存取的利弊,針對DataNode空間浪費過大,NameNode內存占用過高,以及文件索引交互時長過多,從存儲與檢索層面構建了一種基于可擴展分布式文件系統EHDFS架構的解決方案。實驗結果表明,在數據存儲階段,方案通過最優化文件合并的存儲方式,有效提高了DataNode空間利用,并降低了NameNode內存占用。在數據檢索階段,通過改進文件的索引結構設計,有效節省了數據檢索的節點交互時長。所以方案整體上能夠滿足HDFS分布式存取海量農業小文件的需要。但是與MapFile比較,本方案提升有限,仍然具有較大改進空間。