賀建英
摘 要: 針對大數(shù)據(jù)下檔案存儲的現(xiàn)狀,通過分析存儲檔案文檔存在重復(fù)的原因,提出一種MongoDB存儲檔案文檔的方法,利用MongoDB的GridFs統(tǒng)一處理不同類型和大小的文件,定義3個集合分別存儲上傳者記錄、文件信息記錄和分塊文件內(nèi)容,提出存儲中通過文件MD5校驗碼值是否相同來進行去重研究,并實現(xiàn)去重的程序代碼,有一定的實際意義。采用的分布式存儲數(shù)據(jù)庫增強了檔案文檔存儲系統(tǒng)的可擴展性。實驗表明,該方法能有效地去除重復(fù)的檔案文檔,提高查詢效率。
關(guān)鍵詞: MongoDB; MD5; 大數(shù)據(jù); 檔案文檔去重; GridFs
中圖分類號: TN911?34; TP311 文獻標(biāo)識碼: A 文章編號: 1004?373X(2015)16?0051?05
Research on duplicated document removal in big data archive storage of MongoDB database
HE Jianying
(College of Computer, Sichuan University of Arts and Science, Dazhou 635000, China)
Abstract: In allusion to the present situation in document storage in case of big data, the MongoDB method to save documents is proposed according to the reason analysis of duplication in document storage. GridFs of MongoDB is used to store different type documents. Three different assemblages are definited to store the uploader record, document information record and content of blocked documents respectively. A research is proposed for removing the duplication by checking whether MD5 check code is same or not. It is significant to realize program code for duplicated document removal. The distributive memory database was used to enhance the expandability of the document saving system. The experimental result shows that this method can remove the duplicated documents effectively and improve the efficiency of inquiry.
Keywords: MongoDB; MD5; big data; file document duplicate removal; GridFs
0 引 言
隨著信息技術(shù)的飛躍發(fā)展,各國各地都在大力發(fā)展電子政務(wù)建設(shè)。在此環(huán)境下檔案局的檔案文檔也跨入了信息化存儲的行列。但檔案局的檔案類型種類較多,除了純文本的之外,還有圖片、聲音、視頻、PDF等各種類型的文檔,這些文檔都是非結(jié)構(gòu)化的數(shù)據(jù),在傳統(tǒng)的信息系統(tǒng)中,存放這些數(shù)據(jù)是比較困難的。因此在大數(shù)據(jù)環(huán)境下,設(shè)計信息化檔案存儲系統(tǒng)會首選非結(jié)構(gòu)化的數(shù)據(jù)庫,即NoSQL數(shù)據(jù)庫。利用NoSQL家族中的MongoDB數(shù)據(jù)庫作為存放檔案文檔的非結(jié)構(gòu)化數(shù)據(jù)是較為理想的。MongoDB對存放大量的非結(jié)構(gòu)化數(shù)據(jù)有很大的優(yōu)勢,但因MongoDB本身就是非結(jié)構(gòu)化的,故在存放信息時會產(chǎn)生重復(fù)的數(shù)據(jù)。有人提出了像在關(guān)系數(shù)據(jù)庫中一樣建立關(guān)鍵索引來解決重復(fù)數(shù)據(jù)的問題,但在以文檔方式存儲的數(shù)據(jù)而言,當(dāng)數(shù)據(jù)很大時,這種方式將會有弊端。本文研究的是在存儲檔案文檔之前就重復(fù)的數(shù)據(jù)進行去重處理,然后再存入MongoDB數(shù)據(jù)庫中,這樣在數(shù)據(jù)庫中存放的將是非重復(fù)的數(shù)據(jù)。
1 傳統(tǒng)的檔案存儲分析
在原有的存儲檔案文檔信息系統(tǒng)中,主要是把文檔以文件的形式存放在文件系統(tǒng)中,然后用原數(shù)據(jù)信息建立一個檔案文件和數(shù)據(jù)庫的鏈接,并把該鏈接的路徑存儲在關(guān)系數(shù)據(jù)庫中,如表1和表2所示。
通過表1和表2的分析可知,表2中filePathId與表1中的filePathId中的字段關(guān)聯(lián) ,這樣在訪問表1中的某個文件時,只需要訪問表2中與filePathId字段關(guān)聯(lián)的記錄的fileRealPath的值即可訪問該文件。對于以文件系統(tǒng)方式存放的檔案文件會產(chǎn)生大量的重復(fù)文件。即使在存儲的時候能簡單的通過人工的方式來檢查是否有重復(fù)的文件存放,但也不能大面積的檢查是否有重復(fù)的文件,在這種方式下,存儲空間很快會被耗盡,要靠不斷的增加存儲設(shè)備來解決大量檔案數(shù)據(jù)存放的問題,而且不利于管理,數(shù)據(jù)極其不安全,擴展性較差。人們對此已有逐步的認識,也進行了相應(yīng)的研究。本文的重點是利用MongoDB數(shù)據(jù)庫來存儲這些非結(jié)構(gòu)化的數(shù)據(jù),并且在存放之前就完成對重復(fù)檔案文檔的去重操作。
表1 文件基本信息表
表2 文件存儲路徑映射表
2 基于MongoDB的文檔存儲模型
2.1 MongoDB的存儲機制
MongoDB是NoSql家族中的一員,具有模式自由等特性。它與關(guān)系數(shù)據(jù)庫一樣具有3個層次:分別是數(shù)據(jù)庫層、集合層、文檔對象層。分別對應(yīng)關(guān)系數(shù)據(jù)庫中的數(shù)據(jù)庫、表和記錄。在MongoDB中文檔類似于JSON的鍵/值對,集合則是一組文檔的集合,它們是無模式限制的。MongoDB數(shù)據(jù)庫非常適合實時數(shù)據(jù)的插入、查詢、更新、刪除及數(shù)據(jù)備份等操作。尤其適合充當(dāng)由幾十臺或者幾百臺服務(wù)器組成的集群數(shù)據(jù)庫?,F(xiàn)在大多數(shù)的地理規(guī)劃等領(lǐng)域都在利用MongoDB數(shù)據(jù)庫進行數(shù)據(jù)存儲。MongoDB數(shù)據(jù)庫不僅支持分布式系統(tǒng),它本身還支持分片存儲數(shù)據(jù)(Mongod)、客戶端請求(Clients)、集群配置(Config Server)和路由協(xié)議(Mongos)[1]。它采用的是內(nèi)存映射的方式作為存儲引擎,能有效地提高輸入/輸出的效率[2]。endprint
2.2 MongoDB數(shù)據(jù)庫中重復(fù)數(shù)據(jù)來源
目前的檔案管理系統(tǒng)還處于信息孤島的層面,各個省市的數(shù)據(jù)結(jié)構(gòu)不同,存放的方式也不同,惟一能統(tǒng)一的是從市級單位及其下級單位,如區(qū)、縣、鄉(xiāng)、鎮(zhèn)單位。利用檔案管理系統(tǒng)上傳檔案文件進行存儲的也是這些相關(guān)單位。如果同一份檔案文檔被市級單位分發(fā)到其他單位,其他單位會把它作為重要檔案文檔給上傳到檔案管理系統(tǒng)中存儲起來,這樣就會產(chǎn)生多個重復(fù)的檔案文檔。而有部門在不知道的情況下,同一個人上傳了幾份相同的檔案文檔;或者利用shp文件批量上傳檔案文檔時遇到其他異常情況,沒有一次性的上傳完,下次再上傳的時候,又是從頭開始上傳,導(dǎo)致以前的檔案文檔被重復(fù)存儲;或者在批量上傳的shp文檔本身被人為的不小心做成了含有重復(fù)的檔案文檔記錄,這樣導(dǎo)入shp文件時也會產(chǎn)生重復(fù)記錄。通過對以上情況的分析可知,檔案文檔存儲時在MongoDB數(shù)據(jù)庫中產(chǎn)生重復(fù)數(shù)據(jù)的來源主要有以下幾點:同一個檔案文檔被不同的單位、部門重復(fù)上傳;同一個人對同一個檔案文檔上傳多次;批量檔案文檔準備過程中人為的產(chǎn)生了重復(fù)文檔;批量上傳時,中斷上傳,下次再上傳時將產(chǎn)生重復(fù)文檔。
2.3 檔案存儲模型的建立
檔案存儲時采用分布式的方式進行上傳存儲的,各個市、區(qū)、縣、鄉(xiāng)、鎮(zhèn)的不同部門可能在不同的時間和地點對檔案文檔進行上傳操作。數(shù)據(jù)庫采用MongoDB數(shù)據(jù)庫,其分布式存儲結(jié)構(gòu)如圖1所示。
圖1 分布式數(shù)據(jù)庫存儲圖
從圖1可以看出,各市、縣、鄉(xiāng)、鎮(zhèn)的用戶可以隨時在不同地點上傳檔案文檔到不同的MongoDB服務(wù)器中,操作方便。檔案文檔不同于一般的文檔,將遵循“誰操作誰負責(zé)”的原則。故將設(shè)置上傳者的權(quán)限,且將記錄上傳者的詳細信息:如上傳時間、地點等的一些信息。而對于檔案文檔本身而言其文件大小不能統(tǒng)一標(biāo)準化,且檔案文檔的格式有差異,考慮到要處理數(shù)據(jù)大小和類型都可能不同的檔案文檔,本文將借助于MongoDB的GridFs來處理,GridFs是一種處理大文件的規(guī)范,可以存儲上百萬的文件而不用擔(dān)心其擴容性[3]。在MongoDB中存放數(shù)據(jù)時將涉及到3個集合:userInfo.users,fileInfo.files,fileContent.chunks。
userInfo.users集合用來存放上傳檔案文檔的上傳者信息,其結(jié)構(gòu)如下:
{
“_ID”:
“UserID”:
“UploadGeography”: //上傳的地理位置
“GeoType”:
“UploadGeoName”:
“UploadGeoNameID”:< String > //地理名稱主鍵值
“UploadGeoAddress”: //上傳的城鎮(zhèn)地址等
“CityName”:
“CountyName”:< String > //縣級名稱
“TownName”:< String > //鄉(xiāng)鎮(zhèn)名稱
“StreetName”:< String > //街道名稱
“GeoPts”: //地理坐標(biāo)
“Type”:< String > //坐標(biāo)類型
“GeoCoordinates”:< String > //坐標(biāo)位置
“UploadFileID”:< objectID> //上傳存放文件信息的ID編號
“UploadTime”:< timestamp > //上傳者操作的
//體時間
“UploadCount”:
}
fileInfo.files集合中存放信息的結(jié)構(gòu)為:
{
“fileID”:
//存放文件ID值與userInfo.users集合中upLoadFileID對應(yīng)
“fileLength”:< num > //文件的大小
“fileChuckSize”:< num > //文件分塊存儲的分塊數(shù)
“fileName”:< String > //上傳文件的名稱
“fileMD5”:< hash > //文件內(nèi)容的MD5校驗碼值
“fileCountType”:< String > //文件的類型
}
fileContent.chucks集合中存放上傳文檔的結(jié)構(gòu)如下:
{
“f_ID”:< objectID > //惟一的值
“fileID”:< objectID > //與fileInfo.files集
//合中的fileID對應(yīng)
“countOrder”:< num > //存放上傳文件的第幾個分塊
“countData”:< binary > //存放文檔對應(yīng)分塊部分//的二進制內(nèi)容
}
集合fileInfo.files中的fileID與集合userInfo.users集合中的upLaodfileID相同,用來關(guān)聯(lián)上傳的文件信息。集合fileContent.chucks中的fileID與集合fileInfo.files中的fileID相同,用來關(guān)聯(lián)文件存放的具體內(nèi)容,根據(jù)上面3個集合中結(jié)構(gòu)的設(shè)計,當(dāng)一個具有操作權(quán)限的用戶在某一地點上傳了某個檔案文件后,將記錄該用戶上傳的詳細信息:如操作者,上傳的具體區(qū)、縣、鄉(xiāng)的詳細地址,上傳的日期、文件名、文件的大小、長度、類型等。當(dāng)該用戶再次上傳相同的檔案文檔時,根據(jù)表的關(guān)聯(lián)查找,將會做出已在同一地點或不同地點已經(jīng)上傳了相同的檔案文件的提示信息。
3 MongoDB中的去重算法
本算法的設(shè)計思想是,根據(jù)上傳的檔案文檔判斷,無論是否已經(jīng)被上傳過,都會存儲上傳檔案文檔操作者的相關(guān)信息,即生成一個userInfo.users集合中的一條記錄。上傳檔案文件時為了節(jié)省服務(wù)器的開銷和資源,所上傳文檔的MD5 校驗碼值的計算都會在客戶端進行。在客戶端計算并上傳檔案文檔的MD5校驗碼值后再在分布式存儲數(shù)據(jù)庫中查找遍歷fileInfo.files中的每一條記錄,查看每條記錄中存儲的檔案文檔的MD5碼值是否與將要上傳的檔案文檔的MD5碼值相同,如果不同,則將在userInfo.user集合中存儲一條上傳者信息的記錄,并且把該記錄中的“UploadCount”值設(shè)置為1。同時生成集合fileInfo.files中的一條記錄,在該記錄中通過“fileMD5”存儲檔案文檔的MD5碼值。獲得要上傳的檔案文檔的大小fileSize,確定檔案分塊存儲的總塊數(shù)fileChuckSize。在算法中為了規(guī)范,不管文件的大小和類型,均采用統(tǒng)一大?。╢ixedSize)的分塊對檔案文檔進行存放,即總分塊數(shù)如下所示:
fileChuckSize=(fileSize%fixedSize)?(fileSize/fixedSize):
(fileSize/fixedSize+1)
并把該值記錄到fileInfo.files集合中對應(yīng)記錄中。然后對檔案文檔進行上傳并對文檔內(nèi)容按固定的分塊大小存放到fileContent.chucks集合中,在該集合里會存儲fileChuckSize條記錄。如果要上傳的檔案文檔的MD5碼值和分布式數(shù)據(jù)庫中存儲的fileInfo.files集合中存儲的某個記錄的fileMD5值相同,則取出該條記錄對應(yīng)的fileID值并把該值存放到一個臨時存儲字段tempFileID中,已備后期使用。然后提取上傳者的信息和tempFileID的值組合成userInfo.users集合中的一條記錄,并與集合中的其他記錄進行比較,如果有相同的記錄,則在該條記錄的UploadCount值加1。而組合的這條記錄將不再存儲在userInfo.users集合中。其中UploadCount值加1是判斷該用戶是否經(jīng)常在同一個地點上傳相同的檔案文檔。
如果在該集合中沒有相同的記錄,則存儲該組合好的記錄。下次在訪問這個檔案文檔時,通過userInfo.users集合中的upLoadfileID關(guān)聯(lián)到fileInfo.files集合,再通過fileInfo.files集合中的fileID關(guān)聯(lián)到fileContent.chucks集合,則順利訪問到需要的檔案文檔,其過程流程圖如圖2所示。
根據(jù)算法流程圖,定義幾個類UserInfo,F(xiàn)ileInfo,F(xiàn)ileContent分別對應(yīng)3個集合,定義操作數(shù)據(jù)庫的類DBObj,定義去重的類RemoveRepeat。
圖2 算法流程圖
去重的關(guān)鍵代碼實現(xiàn)如下:
/ *在fileInfo.files集合中查找有沒有與指定的hashMD5碼相同的記錄存在*/
private String findByFileMD5(hash fileMD5) {
String tempFileID=null;
List
GeoEntiy ge = null;
/*取得傳遞的fileMD5參數(shù) */
String json = "{fileMD5 : \"" + fileMD5 + "\"}";
DBObj fileMD5 = (DBObj) JSON.parse(json);
DBCursor dbcursor = getDBColl().find(fileMD5);
/* 根據(jù)坐標(biāo)點查詢的記錄數(shù)量*/
int rowCount = dbcursor.count();
/*如果結(jié)果大于0則說明有相同的MD5碼存在,則存放該記錄的fileID值*/
if (rowCount > 0) {
tempFileID= rowCount.get("fileID").toString();
}
}
return tempFileID;
}
public List
/* 構(gòu)建數(shù)據(jù)查重的MongoDB語句,并進行查重 */
DBObj groupObj = new BasicDBObj("$group", JSON.parse(" {_ID: { "
+ " UserID : \"$UserID\" , "
+ " UploadGeography : \"$UploadGeography\" "
+ " GeoType : \"$GeoType\" , "
+ " UploadGeoName : \"$UploadGeoName\" , "
+ " UploadGeoNameID: \"$UploadGeoNameID\" , "
+ " UploadGeoAddress : \"$UploadGeoAddress\" , "
+ " CityName : \"$CityName\" , "
+ " CountyName : \"$CountyName\" , "
+ " TownName : \"$TownName\" , "
+ " StreetName : \"$StreetName\" , "
+ " GeoPts : \"$GeoPts\" , "+ " Type : \"$Type\" , "
+ " GeoCoordinates: \"$UploadFileID\" , "
+ " UploadTime : \"$UploadTime\" , "
+ " UploadCount: \"$UploadCount\");
// 排序條件 ?? 按照關(guān)鍵字_ID降序排列
DBObj sortObj = new BasicDBObj("$sort",JSON.parse("{ _ID:?1 }"));
// 確定疑似重復(fù)數(shù)據(jù)的條件返回的結(jié)果為1
DBObj matchObj = new BasicDBObj("$match",JSON.parse("{ _ID:?1 });
// key code
AggregationOutput output = getDBColl().aggregate(groupObj, sortObj,matchObj);
Iterator
//獲取查詢結(jié)果集
List
while (iter.hasNext()) {
DBObj dbo = iter.next();
String _idValue = dbo.get("_ID").toString();
//通過key,獲取對應(yīng)的value
if (_idValue != null) {//如果查詢結(jié)果不為空,則將結(jié)
果轉(zhuǎn)換
JSONObj pointJson = com.alibaba.fastjson.JSON.parseObject(_idValue);
// 如果存在坐標(biāo)點或有想太多 其他值,則獲取
if (pointJson.get("GeoPts") != null) {
list.addAll(findByPoints(pointJson.get("GeoPts").toString()));
}
}
}
return list;
}
在代碼中定義了findByFileMD5()方法判斷在已經(jīng)存儲的fileInfo.files集合的記錄中有沒有與將要上傳的檔案文檔的MD5校驗碼相同的記錄存在。定義方法findRepeatData()用來檢查有無重復(fù)上傳檔案文檔上傳者信息,即判斷在usersInfo.user中有沒有重復(fù)的數(shù)據(jù)記錄,這些方法在批量導(dǎo)入數(shù)據(jù)記錄時也會調(diào)用逐一判斷。
4 實驗結(jié)果與分析
本實驗使用Hadoop作為分布式文件系統(tǒng)運行在不同地理位置的10臺主機組成的集群上,在Window7系統(tǒng)中,采用MyEclipse8.5做Java代碼開發(fā),分布式數(shù)據(jù)庫MongoDB作數(shù)據(jù)存儲,采用的是8核CPU,8 GB內(nèi)存,320 GB硬盤。批量導(dǎo)入使用的是shp文件。shp文件的格式定義同集合文件的格式。對單個的文檔上傳進行驗證無誤外,為了對更多的數(shù)據(jù)進行驗證,在shp文件中模擬產(chǎn)生10萬,20萬,30萬數(shù)據(jù)。結(jié)果如圖3所示。
圖3 實驗數(shù)據(jù)測試結(jié)果圖
該方法在數(shù)據(jù)去重中達到90%以上,去重效果還比較理想。算法采用的是分布式文件系統(tǒng),對文件去重效率較高,且系統(tǒng)具有相應(yīng)的擴展性。
5 結(jié) 語
本算法中采用分布式文件系統(tǒng)和分布式數(shù)據(jù)庫MongoDB對檔案文檔進行存儲和去重,利用MongoDB數(shù)據(jù)庫的GridFs來處理不同類型和大小的檔案文檔,統(tǒng)一對檔案文檔進行處理。提出利用了去重的算法思想,并通過實驗?zāi)M測試去重效果較為理性。該方法具有一定的可行性。為以后大數(shù)據(jù)的存儲的去重有一定的借鑒性。
參考文獻
[1] 雷德龍,郭殿升,陳崇成,等.基于MongoDB的矢量空間數(shù)據(jù)云存儲與處理系統(tǒng)[J].地理信息科學(xué),2014(7):508?514.
[2] 吳秀君.面向電子政務(wù)的MongoDB與MySQL混合存儲策略[J].計算機與現(xiàn)代化,2014(8):62?65.
[3] CHODOROW Kristina.MongoDB 權(quán)威指南[M].北京:人民郵電出版社,2010.
[4] 郭武士.基于MongoDB GridFS的圖片存儲方案的實現(xiàn)[J].四川工程職業(yè)技術(shù)學(xué)院學(xué)報,2011(4):41?43.
[5] 衛(wèi)啟云,渠偉勇,黃鴻,等.城市地理編碼的部門信息共享與應(yīng)用實踐[J].測繪通報,2014(10):101?104.
[6] 陳超,王亮,閆浩文,等.一種基于NoSQL 的地圖瓦片數(shù)據(jù)存儲技術(shù)[J].測繪科學(xué),2013(1):142?143.
[7] MANBER U. Finding similar files in a large file system [C]// Proceedings of the Winter 1994 USENIX Technical Conference. San Fransisco, CA, USA: [s.n.], 1994: 1?10.
[8] BRODER A Z. On the resemblance and containment of documents [C]// Proceedings of the International Conference on Compression and Complexity of Sequences. Salerno, Italy: [s.n.], 1997: 21?29.
[9] 孫有軍,張大興.海量圖片文件存儲去重技術(shù)研究[J].計算機應(yīng)用與軟件,2014(4):56?57.
[10] RIVEST R. The MD5 message?digest algorithm [J]. RFC 1321, Internet Engineering Task Force, 1992, 22(1) : 15?26.
[11] 成功,李小正,趙全軍.一種網(wǎng)絡(luò)爬蟲系統(tǒng)中URL去重方法的研究[J].中國新技術(shù)新產(chǎn)品,2014(12):23?24.
[12] 楊祥清.存儲系統(tǒng)數(shù)據(jù)去重策略研究[J].信息通信,2014(8):132?133.
[13] 高翔,李兵.中文短文本去重方法研究[J].計算機工程與應(yīng)用,2014(16):196?201.