郭東新,張偉,2,荊忠航
(1.北京信息科技大學(xué)計(jì)算機(jī)學(xué)院,北京100101;2.北京信息科技大學(xué),北京材料基因工程高精尖創(chuàng)新中心,北京100101)
目前,交通和公安等部門在存儲(chǔ)和查詢海量車輛小圖片時(shí),隨著訪問需求和車輛信息的快速增長(zhǎng),對(duì)效率的要求越來越高。同時(shí),在大數(shù)據(jù)平臺(tái)中存儲(chǔ)小圖片時(shí),由于每張車輛圖片的大小均小于HDFS 的數(shù)據(jù)塊大小(默認(rèn)為64MB),而且小圖片的數(shù)據(jù)量為大文件的幾十倍,導(dǎo)致NameNode 內(nèi)存瓶頸、MapReduce 性能降低和高存儲(chǔ)時(shí)間三個(gè)方面[1-4]的問題出現(xiàn)。
因此,研究如何優(yōu)化車輛小圖片的存儲(chǔ),可以提高小圖片的存儲(chǔ)和讀取效率,有助于交通和公安等部對(duì)于海量小文件存儲(chǔ)優(yōu)化的方法,國(guó)內(nèi)外學(xué)者已經(jīng)開展了研究,并提出了一系列操作和方法,主要分為改進(jìn)系統(tǒng)結(jié)構(gòu)、小文件合并和針對(duì)特定場(chǎng)景的小文件合并三種方式。
ElKafrawy P M[5]提出了一種新的結(jié)構(gòu)HDFSX,管理主存儲(chǔ)器的元數(shù)據(jù)。當(dāng)元數(shù)據(jù)量達(dá)到閾值時(shí),將其余元數(shù)據(jù)存儲(chǔ)在閃存上,從而解決主存儲(chǔ)器上元數(shù)據(jù)的內(nèi)存瓶頸問題。Bok K[6]提出了一種分布式緩存方案,使用客戶端和數(shù)據(jù)節(jié)點(diǎn)緩存元數(shù)據(jù),從而有效地提高HDFS 中小文件的訪問性能。Fu S[7]提出了一個(gè)扁平的輕量級(jí)文件系統(tǒng)(iFlatLFS),設(shè)計(jì)一個(gè)簡(jiǎn)單的元數(shù)據(jù)方案和一個(gè)扁平的存儲(chǔ)體系結(jié)構(gòu)進(jìn)行管理小文件,從而顯著減少了元數(shù)據(jù)的數(shù)量。上述方法通過改變系統(tǒng)結(jié)構(gòu),可以有效地解決小文件問題,但是需要改變文件系統(tǒng)或者在現(xiàn)有文件系統(tǒng)上增加額外的緩存節(jié)點(diǎn),增加了系統(tǒng)的建設(shè)成本和復(fù)雜性。
鄭通[8]提出了小文件合并為大文件進(jìn)行存儲(chǔ)的方案,同時(shí)建立了文件預(yù)取機(jī)制來提高文件讀取速度。程晗[9]通過Redis 設(shè)置三類隊(duì)列合并智慧醫(yī)療小文件,同時(shí)通過改進(jìn)的AHP 算法進(jìn)行系統(tǒng)負(fù)載預(yù)測(cè)判斷。Sheoran S[10]提出了將小文件合并成MapFile 進(jìn)行存儲(chǔ)的方案。Cheng W[11]提出了一種基于索引機(jī)制的小文件合并存儲(chǔ)方案,通過創(chuàng)建一個(gè)索引文件來保存小文件的索引信息。上述方法都是先將小文件合并成大文件,再存儲(chǔ)大文件,有效地解決了內(nèi)存瓶頸問題。但是合并小文件時(shí)沒有考慮小文件間的關(guān)聯(lián)關(guān)系,還可進(jìn)一步提高文件讀取速度。
馬振[12]提出了變尺度堆棧算法VSSA 合并小文件,該算法以迭代的方法選取待合并隊(duì)列中最大的小文件進(jìn)行合并,充分地利用數(shù)據(jù)塊存儲(chǔ)空間。游小容[13]利用教育資源中小文件的前赴后繼關(guān)系將小文件合并為大文件。Xiong L[14]利用時(shí)空范圍合并時(shí)空數(shù)據(jù)小文件。Ahad M A[15]提出一種動(dòng)態(tài)合并技術(shù),根據(jù)小文件的大小和類型進(jìn)行合并。Fan Y[16]設(shè)計(jì)了一個(gè)小文件處理系統(tǒng)SFPS,合并相似的小文件,可以減少小文件的數(shù)量和冗余數(shù)據(jù)。Nivedita V[17]根據(jù)用戶訪問的優(yōu)先級(jí)建立小文件合并模型。上述方法都是先將特定場(chǎng)景的小文件合并成大文件,再進(jìn)行存儲(chǔ),可以根據(jù)文件大小和數(shù)據(jù)間關(guān)聯(lián)關(guān)系進(jìn)行合并,不僅解決了內(nèi)存瓶頸問題,還提高了文件讀取速度。但是這種方式只能解決某一特定領(lǐng)域的小文件合并,適用性不高,而且,將合并索引文件與數(shù)據(jù)塊一起存儲(chǔ),導(dǎo)致訪問文件數(shù)據(jù)的速度不快。
綜上可以發(fā)現(xiàn),通過改進(jìn)系統(tǒng)結(jié)構(gòu)可以解決小文件存儲(chǔ)的問題,但是增加了系統(tǒng)的建設(shè)成本和復(fù)雜性。通過合并小文件和特定場(chǎng)景下的小文件后再存儲(chǔ)的兩種方式不但有效地解決了內(nèi)存瓶頸問題,而且提高了文件讀取速度,但是只能解決某一特定領(lǐng)域的文件合并存儲(chǔ)的問題,適用范圍受限制。
因此,本文提出一種基于HDFS+HBase+Redis 的海量車輛小圖片存儲(chǔ)與檢索系統(tǒng)。首先,針對(duì)小圖片存儲(chǔ)的問題提出一種基于關(guān)聯(lián)關(guān)系的合并存儲(chǔ)方法,先根據(jù)車牌號(hào)所屬省份、車身顏色和車型的關(guān)聯(lián)關(guān)系合并小圖片,再存儲(chǔ)到Redis 建立的臨時(shí)隊(duì)列中,待達(dá)到合并文件達(dá)到隊(duì)列大小時(shí)存儲(chǔ)至HDFS 中。然后,提出一種基于冗余策略的存儲(chǔ)優(yōu)化方法,將每一類的合并文件復(fù)制三份,分別存儲(chǔ)在以車牌號(hào)所屬省份為索引的存儲(chǔ)區(qū)域、以車身顏色為索引的存儲(chǔ)區(qū)域和以車型為索引的存儲(chǔ)區(qū)域,并將索引信息存儲(chǔ)在HBase中。最后,針對(duì)提出的海量車輛小圖片的存儲(chǔ)優(yōu)化模型設(shè)計(jì)了一種合理的小圖片檢索流程。可以快速地定位車輛信息,整體了解實(shí)時(shí)的交通狀況,及時(shí)引導(dǎo)車輛的正常行駛。
當(dāng)大小為100KB 的小圖片存儲(chǔ)到默認(rèn)數(shù)據(jù)塊大小為64MB 的HDFS 中,小圖片實(shí)際所占用的硬盤大小為100KB,并非64MB。因此,存儲(chǔ)海量小圖片并不會(huì)產(chǎn)生硬盤壓力,但是,會(huì)增加HDFS 中NameNode 的內(nèi)存消耗,而且,在讀取小圖片時(shí)會(huì)消耗大量時(shí)間。
通常,為了方便查找小圖片存儲(chǔ)在哪個(gè)數(shù)據(jù)塊中,將小圖片的文件名,數(shù)據(jù)塊ID 和數(shù)據(jù)塊存放位置組成元數(shù)據(jù),存儲(chǔ)在HDFS 的Namenode 中。一般情況下元數(shù)據(jù)的大小為250bytes,但是,如果數(shù)據(jù)塊默認(rèn)備份為三個(gè)副本數(shù)據(jù)塊時(shí),新備份的兩個(gè)副本的元數(shù)據(jù)大小則為368bytes。
當(dāng)n個(gè)小圖片進(jìn)行三備份后存儲(chǔ)在HDFS 中,NameNode 的內(nèi)存消耗如式(1)所示。隨著小圖片數(shù)量n的逐漸增加,NameNode 的內(nèi)存消耗越來越大。
其中,a表示HDFS 沒有存儲(chǔ)數(shù)據(jù)時(shí)NameNode本身所占內(nèi)存大?。籦表示每個(gè)數(shù)據(jù)塊的列表信息在NameNode 的內(nèi)存消耗;B表示HDFS 中數(shù)據(jù)塊大小;fi表示在HDFS 中存儲(chǔ)的n個(gè)圖片所占內(nèi)存大小。
當(dāng)小圖片數(shù)據(jù)塊進(jìn)行一備份后存儲(chǔ)在HDFS 中,讀取n個(gè)內(nèi)存大小為fi的小圖片的總耗時(shí)如式(2)所示。隨著小圖片數(shù)量n的逐漸增加,訪問NameNode 和DataNode 的次數(shù)越來越多,讀取時(shí)間越來越長(zhǎng)。
其中,Trequ表示NameNode 接收檢索請(qǐng)求的時(shí)間消耗;Tquer表示NameNode 查詢?cè)獢?shù)據(jù)的時(shí)間消耗;Tresu表示NameNode 返回目標(biāo)元數(shù)據(jù)的時(shí)間消耗;Tacce表示用戶在DataNode 中檢索目標(biāo)文件的消耗;Tdata表示DataNode 查詢目標(biāo)小圖片的時(shí)間消耗;Tfile表示DataNode 返回目標(biāo)小圖片的時(shí)間消耗。
根據(jù)上述關(guān)于NameNode 的內(nèi)存消耗和小圖片讀取時(shí)間的理論分析,可以發(fā)現(xiàn),如果想解決海量小圖片存儲(chǔ)時(shí)產(chǎn)生的NameNode 內(nèi)存消耗和小圖片訪問延遲的兩個(gè)問題,需要減少NameNode 的元數(shù)據(jù)的個(gè)數(shù),減少NameNode 的訪問次數(shù)和降低DataNode 讀取目標(biāo)數(shù)據(jù)塊的時(shí)間。
在Hadoop 大數(shù)據(jù)平臺(tái)上存儲(chǔ)海量的車輛小圖片時(shí),由于每張小圖片的大小均小于HDFS 的數(shù)據(jù)塊大?。?4MB),則會(huì)出現(xiàn)NameNode 內(nèi)存瓶頸,MapReduce處理性能降低和存儲(chǔ)耗時(shí)太長(zhǎng)等問題?,F(xiàn)有的方法為了降低NameNode 內(nèi)存占用較高的問題,一般采用先將小文件合并成大文件,再存儲(chǔ)大文件的過程。該方法可以解決內(nèi)存瓶頸問題,但是在合并時(shí)未考慮圖片之間關(guān)聯(lián)關(guān)系。
因此,本文提出了一種基于關(guān)聯(lián)關(guān)系的合并存儲(chǔ)方法。首先,建立初始臨時(shí)隊(duì)列,將存入一張初始圖片。然后,判斷待存儲(chǔ)圖片是否與其中一個(gè)臨時(shí)隊(duì)列中的初始圖片具有相同的省份車牌號(hào)、相同的車身顏色和相同車型,若完全相同,則將待存儲(chǔ)圖片合并到臨時(shí)隊(duì)列中,否則新建一個(gè)臨時(shí)隊(duì)列,將待存儲(chǔ)圖片作為新建臨時(shí)隊(duì)列的初始圖片,重復(fù)上述操作,直至所有的待存儲(chǔ)圖片上傳至HDFS 進(jìn)行存儲(chǔ)。具體的操作步驟如下所示。
(1)初始時(shí),使用Redis 建立一個(gè)臨時(shí)隊(duì)列q0,從小圖片序列P={p0,p1,...,pn}中取出一張圖片p0,進(jìn)入隊(duì)列q0中,作為隊(duì)列q0的初始圖片。
(2)從序列qi中取出小圖片pi,然后判斷每次取出的pi與現(xiàn)存所有臨時(shí)隊(duì)列中的初始圖片是否具有相同省份的車牌號(hào)、相同車身顏色和相同車型,若pi與某一個(gè)臨時(shí)隊(duì)列qi中的初始圖片具有相同省份的車牌號(hào)、相同車身顏色和相同車型,則pi進(jìn)入臨時(shí)隊(duì)列qi中;否則,Redis 新建一個(gè)臨時(shí)隊(duì)列qj,pi進(jìn)入臨時(shí)隊(duì)列qj中,作為隊(duì)列qj的初始圖片。
(3)當(dāng)臨時(shí)隊(duì)列qi接收pi的等待時(shí)間超過設(shè)置的時(shí)間閾值,若超時(shí),將隊(duì)列qi中的合并文件上傳至HDFS 進(jìn)行存儲(chǔ)。
(4)當(dāng)pi進(jìn)入臨時(shí)隊(duì)列qi后,判斷隊(duì)列中文件的總大小是否超過設(shè)置的HDFS 數(shù)據(jù)塊大小,若超過,也將隊(duì)列qi中的合并文件上傳至HDFS 進(jìn)行存儲(chǔ);否則,繼續(xù)執(zhí)行步驟(2)~(4),直至序列P為空;
(5)當(dāng)序列P為空時(shí),將所有臨時(shí)隊(duì)列中未達(dá)到數(shù)據(jù)塊大小的合并文件上傳至HDFS 進(jìn)行存儲(chǔ)。
當(dāng)合并文件上傳至HDFS 后,隨機(jī)地存儲(chǔ)在HDFS中的存儲(chǔ)區(qū)域。若查詢紅色車輛的信息,需要訪問所有的存儲(chǔ)區(qū)域,若查詢轎車的信息,也需要訪問所有的存儲(chǔ)區(qū)域。所以,當(dāng)車輛小圖片的存儲(chǔ)系統(tǒng)在某一時(shí)段進(jìn)行大量查詢請(qǐng)求時(shí),大大增加了工作節(jié)點(diǎn)的任務(wù)數(shù)。因此,為了提高存儲(chǔ)系統(tǒng)的吞吐率和降低系統(tǒng)負(fù)載,本文在不增加額外系統(tǒng)開銷的前提下,利用Hadoop數(shù)據(jù)塊的三備份機(jī)制,設(shè)計(jì)了一種基于冗余策略的存儲(chǔ)優(yōu)化模型,如圖1 所示。
圖1 基于冗余策略的存儲(chǔ)優(yōu)化模型
如圖1 所示,首先,基于冗余策略的存儲(chǔ)優(yōu)化模型根據(jù)Hadoop 數(shù)據(jù)塊的備份機(jī)制,將上傳至HDFS 中的n 類車輛的合并文件數(shù)據(jù)塊復(fù)制成三份,然后將每一類車輛的三份合并文件分別存儲(chǔ)在以車牌號(hào)的索引的存儲(chǔ)區(qū)域1、以車身顏色為索引的存儲(chǔ)區(qū)域2 和以車型為索引的存儲(chǔ)區(qū)域3。
當(dāng)車輛小圖片的合并文件在HDFS 中優(yōu)化存儲(chǔ)后,為了能夠快速檢索到合并文件中的車輛小圖片,本文還提出了合并索引機(jī)制。將合并文件的三份數(shù)據(jù)塊分別按照車牌號(hào)所屬省份、車身顏色和車型建立三種索引信息,并將索引存儲(chǔ)在HBase 中。然而,為了避免在HBase 中出現(xiàn)訪問熱點(diǎn)的問題,將車牌號(hào)所屬省份和32 位隨機(jī)hash 值組合作為車牌號(hào)索引信息的Rowkey 的命名格式,索引信息結(jié)構(gòu)如表1 所示。將車身顏色和32 位隨機(jī)hash 值組合作為車身顏色索引信息的Rowkey 的命名格式,索引信息結(jié)構(gòu)如表2 所示。將車型和32 位隨機(jī)hash 值組合作為車型索引信息的Rowkey 的命名格式,索引信息如表3 所示。
表1 車牌號(hào)所屬省份的索引信息結(jié)構(gòu)
表2 車身顏色的索引信息結(jié)構(gòu)
表3 車型索引信息結(jié)構(gòu)
以表1 所示的車牌所屬省份的索引信息結(jié)構(gòu)為例,每個(gè)合并文件的Rowkey 為省份_32 位hash 值,每個(gè)Rowkey 記錄了合并文件的數(shù)據(jù)塊ID、每個(gè)小圖片的車牌號(hào)、小圖片在合并文件中的偏移量和長(zhǎng)度。當(dāng)用戶需要獲取某一個(gè)車牌號(hào)的小圖片時(shí),先根據(jù)車牌號(hào)所屬省份在車牌號(hào)索引信息中查找到合并文件的索引記錄,再根據(jù)索引記錄中小圖片的偏移量和長(zhǎng)度找到小圖片的存儲(chǔ)位置,獲取到小圖片。
基于第2 章提出的海量車輛小圖片的存儲(chǔ)方案,本文給出了對(duì)應(yīng)的車輛小圖片的檢索方案,檢索流程圖如圖2 所示。具體的流程如下所示。
圖2 車輛小圖片的檢索流程
(1)根據(jù)小圖片的檢索請(qǐng)求,從Redis 緩存的合并文件的索引中查詢是否存在該小圖片的合并文件,如果存在,獲取合并文件的數(shù)據(jù)塊ID 和元數(shù)據(jù)信息,直接訪問DataNode,讀取出小圖片,將圖片返回給用戶。
(2)如果不存在的話,則開始判斷檢索請(qǐng)求的條件,如果檢索條件的個(gè)數(shù)為1 的話,只需按照檢索條件查詢一個(gè)查詢區(qū)域,獲取小圖片的存儲(chǔ)地址。假設(shè)查找白色的車輛圖片,則只需從以車身顏色為索引的存儲(chǔ)區(qū)域篩選出白色車輛的數(shù)據(jù)塊。
(3)如果檢索條件的個(gè)數(shù)超過1 時(shí),則按照檢索條件分別從各自的存儲(chǔ)區(qū)域查找數(shù)據(jù)。然后,對(duì)分別查找出來的數(shù)據(jù)進(jìn)行去重操作:①當(dāng)查詢條件存在車牌號(hào)時(shí),只按照車牌號(hào)去重;②當(dāng)查詢條件不存在車牌號(hào)時(shí),則采用加速穩(wěn)健特征算法(Speed Up Robust Feature,SURF)計(jì)算圖片之間的相似度,如果兩張圖片的相似度達(dá)到閾值時(shí),進(jìn)行去重后獲取到小圖片。
(4)讀取出去重后的圖片,將圖片返回給用戶。
(5)根據(jù)數(shù)據(jù)預(yù)取機(jī)制將該合并文件的索引信息和元數(shù)據(jù)信息緩存在Redis 中。
本文搭建了一個(gè)實(shí)驗(yàn)平臺(tái),主要用于測(cè)試存儲(chǔ)優(yōu)化方案在存儲(chǔ)小圖片時(shí)的內(nèi)存消耗變化和讀取小圖片的效率變化。實(shí)驗(yàn)平臺(tái)的硬件配置是:8G 內(nèi)存,4 核CPU和200G 的硬盤服務(wù)器。實(shí)驗(yàn)數(shù)據(jù):小圖片大小訪問是30KB 到40KB。本文實(shí)驗(yàn)以HDFS 的NameNode 的內(nèi)存占用、小圖片數(shù)量和小圖片讀取的時(shí)間作為評(píng)價(jià)指標(biāo),將實(shí)驗(yàn)結(jié)果與原生HDFS 的實(shí)驗(yàn)結(jié)果進(jìn)行對(duì)比。
對(duì)于本文提出的存儲(chǔ)優(yōu)化模型,小圖片讀取的時(shí)間包括小圖片的合并時(shí)間t1和合并文件存入HDFS 的時(shí)間t2,考慮到合并文件中小圖片的數(shù)據(jù)量S,因此本文提出的存儲(chǔ)優(yōu)化模型的小圖片平均存儲(chǔ)時(shí)間為T=(t1+t2)/S。對(duì)于原生HDFS 只直接存儲(chǔ)小圖片,不進(jìn)行小圖片的合并,因此,小圖片的存儲(chǔ)時(shí)間為存儲(chǔ)時(shí)間t。
第一組實(shí)驗(yàn)是為了驗(yàn)證本文提出的存儲(chǔ)優(yōu)化方案能夠降低存儲(chǔ)小圖片的內(nèi)存占用,與原生HDFS 在相同的實(shí)驗(yàn)環(huán)境下進(jìn)行對(duì)比實(shí)驗(yàn),分析隨機(jī)讀取小圖片時(shí)NameNode 的內(nèi)存占用情況,對(duì)比實(shí)驗(yàn)結(jié)果如圖3 所示。
圖3 內(nèi)存占用對(duì)比圖
從圖3 中可以看出,當(dāng)小圖片數(shù)量不超過10000個(gè)時(shí),本文提出的存儲(chǔ)優(yōu)化模型的優(yōu)化效果并不明顯,但是隨著小圖片的數(shù)據(jù)量不斷的增加,存儲(chǔ)優(yōu)化模型比原生HDFS 能夠明顯降低NameNode 的內(nèi)存占用。
第二組實(shí)驗(yàn)是為了驗(yàn)證本文提出的存儲(chǔ)優(yōu)化模型能夠提高小圖片的讀取速率,與原生HDFS 在相同的實(shí)驗(yàn)環(huán)境下進(jìn)行對(duì)比實(shí)驗(yàn),分析小圖片的存儲(chǔ)時(shí)間,對(duì)比實(shí)驗(yàn)結(jié)果如圖4 所示。
圖4 小圖片讀取時(shí)間對(duì)比圖
從圖4 中可以看出,本文提出的存儲(chǔ)優(yōu)化模型能夠在小圖片讀取時(shí)間上優(yōu)于原有HDFS。雖然小圖片的合并和索引建立兩個(gè)過程消耗了一定的時(shí)間,但是,隨著小圖片的數(shù)量逐漸增加,建立索引優(yōu)化了小文件的存儲(chǔ)過程,兩個(gè)操作消耗的時(shí)間相對(duì)于小圖片的存儲(chǔ)時(shí)間可以忽略不計(jì)。并且,先合并小圖片再存儲(chǔ)可以減少元數(shù)據(jù)的數(shù)據(jù)量,從而減少了存儲(chǔ)小圖片時(shí)檢索HDFS 空閑塊的時(shí)間。在讀取小圖片方面,本文提出的優(yōu)化方案加入了基于Redis 預(yù)取相關(guān)小圖片機(jī)制,將和正在訪問的數(shù)據(jù)集有關(guān)的小圖片元數(shù)據(jù)預(yù)取在內(nèi)存中。因此,本文提出的存儲(chǔ)優(yōu)化模型能夠很好的降低小圖片的讀取時(shí)間。
為了降低海量車輛小圖片存儲(chǔ)的NameNode 內(nèi)存消耗和提高小圖片的讀取時(shí)間,本文首先對(duì)這兩個(gè)問題進(jìn)行了理論分析,可以發(fā)現(xiàn),隨著小圖片數(shù)量的逐漸增加,NameNode 的內(nèi)存消耗越來越大,訪問NameNode和DataNode 的次數(shù)越來越多,讀取時(shí)間越來越長(zhǎng)。然后提出一種基于關(guān)聯(lián)關(guān)系的合并存儲(chǔ)方法,根據(jù)車輛小圖片的車牌號(hào)所屬省份、車身顏色和車型的關(guān)聯(lián)關(guān)系,合并具有相同信息的小圖片。進(jìn)一步又提出了基于冗余策略的存儲(chǔ)優(yōu)化,將合并文件的數(shù)據(jù)塊進(jìn)行三備份,按照順序分別存儲(chǔ)在以車牌號(hào)所屬省份為索引的存儲(chǔ)區(qū)域、以車身顏色為索引的存儲(chǔ)區(qū)域和以車型為索引的存儲(chǔ)區(qū)域。從而減少了NameNode 的訪問次數(shù)。接著,將索引信息存儲(chǔ)在HBase 中,并且在Rowkey 中添加了32 位的hash 值以避免訪問熱點(diǎn)問題的出現(xiàn)。最后,當(dāng)檢索條件的個(gè)數(shù)為1 和不為1 時(shí),給出了對(duì)應(yīng)的小圖片檢索流程。
對(duì)比實(shí)驗(yàn)結(jié)果表明,本文方法不但能夠明顯降低小圖片在HDFS 中存儲(chǔ)時(shí)的內(nèi)存占用,而且讀取小圖片的時(shí)間更短。