賀建英



摘 要: 針對大數據下檔案存儲的現狀,通過分析存儲檔案文檔存在重復的原因,提出一種MongoDB存儲檔案文檔的方法,利用MongoDB的GridFs統一處理不同類型和大小的文件,定義3個集合分別存儲上傳者記錄、文件信息記錄和分塊文件內容,提出存儲中通過文件MD5校驗碼值是否相同來進行去重研究,并實現去重的程序代碼,有一定的實際意義。采用的分布式存儲數據庫增強了檔案文檔存儲系統的可擴展性。實驗表明,該方法能有效地去除重復的檔案文檔,提高查詢效率。
關鍵詞: MongoDB; MD5; 大數據; 檔案文檔去重; GridFs
中圖分類號: TN911?34; TP311 文獻標識碼: 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 引 言
隨著信息技術的飛躍發展,各國各地都在大力發展電子政務建設。在此環境下檔案局的檔案文檔也跨入了信息化存儲的行列。但檔案局的檔案類型種類較多,除了純文本的之外,還有圖片、聲音、視頻、PDF等各種類型的文檔,這些文檔都是非結構化的數據,在傳統的信息系統中,存放這些數據是比較困難的。因此在大數據環境下,設計信息化檔案存儲系統會首選非結構化的數據庫,即NoSQL數據庫。利用NoSQL家族中的MongoDB數據庫作為存放檔案文檔的非結構化數據是較為理想的。MongoDB對存放大量的非結構化數據有很大的優勢,但因MongoDB本身就是非結構化的,故在存放信息時會產生重復的數據。有人提出了像在關系數據庫中一樣建立關鍵索引來解決重復數據的問題,但在以文檔方式存儲的數據而言,當數據很大時,這種方式將會有弊端。本文研究的是在存儲檔案文檔之前就重復的數據進行去重處理,然后再存入MongoDB數據庫中,這樣在數據庫中存放的將是非重復的數據。
1 傳統的檔案存儲分析
在原有的存儲檔案文檔信息系統中,主要是把文檔以文件的形式存放在文件系統中,然后用原數據信息建立一個檔案文件和數據庫的鏈接,并把該鏈接的路徑存儲在關系數據庫中,如表1和表2所示。
通過表1和表2的分析可知,表2中filePathId與表1中的filePathId中的字段關聯 ,這樣在訪問表1中的某個文件時,只需要訪問表2中與filePathId字段關聯的記錄的fileRealPath的值即可訪問該文件。對于以文件系統方式存放的檔案文件會產生大量的重復文件。即使在存儲的時候能簡單的通過人工的方式來檢查是否有重復的文件存放,但也不能大面積的檢查是否有重復的文件,在這種方式下,存儲空間很快會被耗盡,要靠不斷的增加存儲設備來解決大量檔案數據存放的問題,而且不利于管理,數據極其不安全,擴展性較差。人們對此已有逐步的認識,也進行了相應的研究。本文的重點是利用MongoDB數據庫來存儲這些非結構化的數據,并且在存放之前就完成對重復檔案文檔的去重操作。
表1 文件基本信息表
表2 文件存儲路徑映射表
2 基于MongoDB的文檔存儲模型
2.1 MongoDB的存儲機制
MongoDB是NoSql家族中的一員,具有模式自由等特性。它與關系數據庫一樣具有3個層次:分別是數據庫層、集合層、文檔對象層。分別對應關系數據庫中的數據庫、表和記錄。在MongoDB中文檔類似于JSON的鍵/值對,集合則是一組文檔的集合,它們是無模式限制的。MongoDB數據庫非常適合實時數據的插入、查詢、更新、刪除及數據備份等操作。尤其適合充當由幾十臺或者幾百臺服務器組成的集群數據庫。現在大多數的地理規劃等領域都在利用MongoDB數據庫進行數據存儲。MongoDB數據庫不僅支持分布式系統,它本身還支持分片存儲數據(Mongod)、客戶端請求(Clients)、集群配置(Config Server)和路由協議(Mongos)[1]。它采用的是內存映射的方式作為存儲引擎,能有效地提高輸入/輸出的效率[2]。endprint
2.2 MongoDB數據庫中重復數據來源
目前的檔案管理系統還處于信息孤島的層面,各個省市的數據結構不同,存放的方式也不同,惟一能統一的是從市級單位及其下級單位,如區、縣、鄉、鎮單位。利用檔案管理系統上傳檔案文件進行存儲的也是這些相關單位。如果同一份檔案文檔被市級單位分發到其他單位,其他單位會把它作為重要檔案文檔給上傳到檔案管理系統中存儲起來,這樣就會產生多個重復的檔案文檔。而有部門在不知道的情況下,同一個人上傳了幾份相同的檔案文檔;或者利用shp文件批量上傳檔案文檔時遇到其他異常情況,沒有一次性的上傳完,下次再上傳的時候,又是從頭開始上傳,導致以前的檔案文檔被重復存儲;或者在批量上傳的shp文檔本身被人為的不小心做成了含有重復的檔案文檔記錄,這樣導入shp文件時也會產生重復記錄。通過對以上情況的分析可知,檔案文檔存儲時在MongoDB數據庫中產生重復數據的來源主要有以下幾點:同一個檔案文檔被不同的單位、部門重復上傳;同一個人對同一個檔案文檔上傳多次;批量檔案文檔準備過程中人為的產生了重復文檔;批量上傳時,中斷上傳,下次再上傳時將產生重復文檔。
2.3 檔案存儲模型的建立
檔案存儲時采用分布式的方式進行上傳存儲的,各個市、區、縣、鄉、鎮的不同部門可能在不同的時間和地點對檔案文檔進行上傳操作。數據庫采用MongoDB數據庫,其分布式存儲結構如圖1所示。
圖1 分布式數據庫存儲圖
從圖1可以看出,各市、縣、鄉、鎮的用戶可以隨時在不同地點上傳檔案文檔到不同的MongoDB服務器中,操作方便。檔案文檔不同于一般的文檔,將遵循“誰操作誰負責”的原則。故將設置上傳者的權限,且將記錄上傳者的詳細信息:如上傳時間、地點等的一些信息。而對于檔案文檔本身而言其文件大小不能統一標準化,且檔案文檔的格式有差異,考慮到要處理數據大小和類型都可能不同的檔案文檔,本文將借助于MongoDB的GridFs來處理,GridFs是一種處理大文件的規范,可以存儲上百萬的文件而不用擔心其擴容性[3]。在MongoDB中存放數據時將涉及到3個集合:userInfo.users,fileInfo.files,fileContent.chunks。
userInfo.users集合用來存放上傳檔案文檔的上傳者信息,其結構如下:
{
“_ID”:
“UserID”:
“UploadGeography”: //上傳的地理位置
“GeoType”:
“UploadGeoName”:
“UploadGeoNameID”:< String > //地理名稱主鍵值
“UploadGeoAddress”: //上傳的城鎮地址等
“CityName”:
“CountyName”:< String > //縣級名稱
“TownName”:< String > //鄉鎮名稱
“StreetName”:< String > //街道名稱
“GeoPts”: //地理坐標
“Type”:< String > //坐標類型
“GeoCoordinates”:< String > //坐標位置
“UploadFileID”:< objectID> //上傳存放文件信息的ID編號
“UploadTime”:< timestamp > //上傳者操作的
//體時間
“UploadCount”:
}
fileInfo.files集合中存放信息的結構為:
{
“fileID”:
//存放文件ID值與userInfo.users集合中upLoadFileID對應
“fileLength”:< num > //文件的大小
“fileChuckSize”:< num > //文件分塊存儲的分塊數
“fileName”:< String > //上傳文件的名稱
“fileMD5”:< hash > //文件內容的MD5校驗碼值
“fileCountType”:< String > //文件的類型
}
fileContent.chucks集合中存放上傳文檔的結構如下:
{
“f_ID”:< objectID > //惟一的值
“fileID”:< objectID > //與fileInfo.files集
//合中的fileID對應
“countOrder”:< num > //存放上傳文件的第幾個分塊
“countData”:< binary > //存放文檔對應分塊部分//的二進制內容
}
集合fileInfo.files中的fileID與集合userInfo.users集合中的upLaodfileID相同,用來關聯上傳的文件信息。集合fileContent.chucks中的fileID與集合fileInfo.files中的fileID相同,用來關聯文件存放的具體內容,根據上面3個集合中結構的設計,當一個具有操作權限的用戶在某一地點上傳了某個檔案文件后,將記錄該用戶上傳的詳細信息:如操作者,上傳的具體區、縣、鄉的詳細地址,上傳的日期、文件名、文件的大小、長度、類型等。當該用戶再次上傳相同的檔案文檔時,根據表的關聯查找,將會做出已在同一地點或不同地點已經上傳了相同的檔案文件的提示信息。
3 MongoDB中的去重算法
本算法的設計思想是,根據上傳的檔案文檔判斷,無論是否已經被上傳過,都會存儲上傳檔案文檔操作者的相關信息,即生成一個userInfo.users集合中的一條記錄。上傳檔案文件時為了節省服務器的開銷和資源,所上傳文檔的MD5 校驗碼值的計算都會在客戶端進行。在客戶端計算并上傳檔案文檔的MD5校驗碼值后再在分布式存儲數據庫中查找遍歷fileInfo.files中的每一條記錄,查看每條記錄中存儲的檔案文檔的MD5碼值是否與將要上傳的檔案文檔的MD5碼值相同,如果不同,則將在userInfo.user集合中存儲一條上傳者信息的記錄,并且把該記錄中的“UploadCount”值設置為1。同時生成集合fileInfo.files中的一條記錄,在該記錄中通過“fileMD5”存儲檔案文檔的MD5碼值。獲得要上傳的檔案文檔的大小fileSize,確定檔案分塊存儲的總塊數fileChuckSize。在算法中為了規范,不管文件的大小和類型,均采用統一大小(fixedSize)的分塊對檔案文檔進行存放,即總分塊數如下所示:
fileChuckSize=(fileSize%fixedSize)?(fileSize/fixedSize):
(fileSize/fixedSize+1)
并把該值記錄到fileInfo.files集合中對應記錄中。然后對檔案文檔進行上傳并對文檔內容按固定的分塊大小存放到fileContent.chucks集合中,在該集合里會存儲fileChuckSize條記錄。如果要上傳的檔案文檔的MD5碼值和分布式數據庫中存儲的fileInfo.files集合中存儲的某個記錄的fileMD5值相同,則取出該條記錄對應的fileID值并把該值存放到一個臨時存儲字段tempFileID中,已備后期使用。然后提取上傳者的信息和tempFileID的值組合成userInfo.users集合中的一條記錄,并與集合中的其他記錄進行比較,如果有相同的記錄,則在該條記錄的UploadCount值加1。而組合的這條記錄將不再存儲在userInfo.users集合中。其中UploadCount值加1是判斷該用戶是否經常在同一個地點上傳相同的檔案文檔。
如果在該集合中沒有相同的記錄,則存儲該組合好的記錄。下次在訪問這個檔案文檔時,通過userInfo.users集合中的upLoadfileID關聯到fileInfo.files集合,再通過fileInfo.files集合中的fileID關聯到fileContent.chucks集合,則順利訪問到需要的檔案文檔,其過程流程圖如圖2所示。
根據算法流程圖,定義幾個類UserInfo,FileInfo,FileContent分別對應3個集合,定義操作數據庫的類DBObj,定義去重的類RemoveRepeat。
圖2 算法流程圖
去重的關鍵代碼實現如下:
/ *在fileInfo.files集合中查找有沒有與指定的hashMD5碼相同的記錄存在*/
private String findByFileMD5(hash fileMD5) {
String tempFileID=null;
List
GeoEntiy ge = null;
/*取得傳遞的fileMD5參數 */
String json = "{fileMD5 : \"" + fileMD5 + "\"}";
DBObj fileMD5 = (DBObj) JSON.parse(json);
DBCursor dbcursor = getDBColl().find(fileMD5);
/* 根據坐標點查詢的記錄數量*/
int rowCount = dbcursor.count();
/*如果結果大于0則說明有相同的MD5碼存在,則存放該記錄的fileID值*/
if (rowCount > 0) {
tempFileID= rowCount.get("fileID").toString();
}
}
return tempFileID;
}
public List
/* 構建數據查重的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\");
// 排序條件 ?? 按照關鍵字_ID降序排列
DBObj sortObj = new BasicDBObj("$sort",JSON.parse("{ _ID:?1 }"));
// 確定疑似重復數據的條件返回的結果為1
DBObj matchObj = new BasicDBObj("$match",JSON.parse("{ _ID:?1 });
// key code
AggregationOutput output = getDBColl().aggregate(groupObj, sortObj,matchObj);
Iterator
//獲取查詢結果集
List
while (iter.hasNext()) {
DBObj dbo = iter.next();
String _idValue = dbo.get("_ID").toString();
//通過key,獲取對應的value
if (_idValue != null) {//如果查詢結果不為空,則將結
果轉換
JSONObj pointJson = com.alibaba.fastjson.JSON.parseObject(_idValue);
// 如果存在坐標點或有想太多 其他值,則獲取
if (pointJson.get("GeoPts") != null) {
list.addAll(findByPoints(pointJson.get("GeoPts").toString()));
}
}
}
return list;
}
在代碼中定義了findByFileMD5()方法判斷在已經存儲的fileInfo.files集合的記錄中有沒有與將要上傳的檔案文檔的MD5校驗碼相同的記錄存在。定義方法findRepeatData()用來檢查有無重復上傳檔案文檔上傳者信息,即判斷在usersInfo.user中有沒有重復的數據記錄,這些方法在批量導入數據記錄時也會調用逐一判斷。
4 實驗結果與分析
本實驗使用Hadoop作為分布式文件系統運行在不同地理位置的10臺主機組成的集群上,在Window7系統中,采用MyEclipse8.5做Java代碼開發,分布式數據庫MongoDB作數據存儲,采用的是8核CPU,8 GB內存,320 GB硬盤。批量導入使用的是shp文件。shp文件的格式定義同集合文件的格式。對單個的文檔上傳進行驗證無誤外,為了對更多的數據進行驗證,在shp文件中模擬產生10萬,20萬,30萬數據。結果如圖3所示。
圖3 實驗數據測試結果圖
該方法在數據去重中達到90%以上,去重效果還比較理想。算法采用的是分布式文件系統,對文件去重效率較高,且系統具有相應的擴展性。
5 結 語
本算法中采用分布式文件系統和分布式數據庫MongoDB對檔案文檔進行存儲和去重,利用MongoDB數據庫的GridFs來處理不同類型和大小的檔案文檔,統一對檔案文檔進行處理。提出利用了去重的算法思想,并通過實驗模擬測試去重效果較為理性。該方法具有一定的可行性。為以后大數據的存儲的去重有一定的借鑒性。
參考文獻
[1] 雷德龍,郭殿升,陳崇成,等.基于MongoDB的矢量空間數據云存儲與處理系統[J].地理信息科學,2014(7):508?514.
[2] 吳秀君.面向電子政務的MongoDB與MySQL混合存儲策略[J].計算機與現代化,2014(8):62?65.
[3] CHODOROW Kristina.MongoDB 權威指南[M].北京:人民郵電出版社,2010.
[4] 郭武士.基于MongoDB GridFS的圖片存儲方案的實現[J].四川工程職業技術學院學報,2011(4):41?43.
[5] 衛啟云,渠偉勇,黃鴻,等.城市地理編碼的部門信息共享與應用實踐[J].測繪通報,2014(10):101?104.
[6] 陳超,王亮,閆浩文,等.一種基于NoSQL 的地圖瓦片數據存儲技術[J].測繪科學,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] 孫有軍,張大興.海量圖片文件存儲去重技術研究[J].計算機應用與軟件,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] 成功,李小正,趙全軍.一種網絡爬蟲系統中URL去重方法的研究[J].中國新技術新產品,2014(12):23?24.
[12] 楊祥清.存儲系統數據去重策略研究[J].信息通信,2014(8):132?133.
[13] 高翔,李兵.中文短文本去重方法研究[J].計算機工程與應用,2014(16):196?201.