Hadoop HDFS之SequenceFile和MapFile

來源:http://blog.csdn.net/keda8997110/article/details/8514908


Hadoop的HDFS和MapReduce子框架主要是針對大數據文件來設計的,在小文件的處理上不但效率低下,而且十分消耗磁盤空間(每一個小文件佔用一個Block,HDFS默認block大小爲64M)。解決辦法通常是選擇一個容器,將這些小文件組織起來統一存儲。HDFS提供了兩種類型的容器,分別是SequenceFile和MapFile。

一、SequenceFile

SequenceFile的存儲類似於Log文件,所不同的是Log File的每條記錄的是純文本數據,而SequenceFile的每條記錄是可序列化的字符數組。

SequenceFile可通過如下API來完成新記錄的添加操作:

        fileWriter.append(key,value)

可以看到,每條記錄以鍵值對的方式進行組織,但前提是Key和Value需具備序列化和反序列化的功能

Hadoop預定義了一些Key Class和Value Class,他們直接或間接實現了Writable接口,滿足了該功能,包括:

Text                                等同於Java中的String
IntWritable                   等同於Java中的Int
BooleanWritable        等同於Java中的Boolean
        .
        .

在存儲結構上,SequenceFile主要由一個Header後跟多條Record組成,如圖所示:

Header主要包含了Key classname,Value classname,存儲壓縮算法,用戶自定義元數據等信息,此外,還包含了一些同步標識,用於快速定位到記錄的邊界。

每條Record以鍵值對的方式進行存儲,用來表示它的字符數組可依次解析成:記錄的長度、Key的長度、Key值和Value值,並且Value值的結構取決於該記錄是否被壓縮。

數據壓縮有利於節省磁盤空間和加快網絡傳輸,SeqeunceFile支持兩種格式的數據壓縮,分別是:record compression和block compression。

record compression如上圖所示,是對每條記錄的value進行壓縮

block compression是將一連串的record組織到一起,統一壓縮成一個block,如圖所示:

block信息主要存儲了:塊所包含的記錄數、每條記錄Key長度的集合、每條記錄Key值的集合、每條記錄Value長度的集合和每條記錄Value值的集合

注:每個block的大小是可通過io.seqfile.compress.blocksize屬性來指定的

示例:SequenceFile讀/寫 操作

[java]
  1. Configuration conf=new Configuration();  
  2. FileSystem fs=FileSystem.get(conf);  
  3. Path seqFile=new Path("seqFile.seq");  
  4. //Reader內部類用於文件的讀取操作   
  5. SequenceFile.Reader reader=new SequenceFile.Reader(fs,seqFile,conf);  
  6. //Writer內部類用於文件的寫操作,假設Key和Value都爲Text類型   
  7. SequenceFile.Writer writer=new SequenceFile.Writer(fs,conf,seqFile,Text.class,Text.class);  
  8. //通過writer向文檔中寫入記錄   
  9. writer.append(new Text("key"),new Text("value"));  
  10. IOUtils.closeStream(writer);//關閉write流   
  11. //通過reader從文檔中讀取記錄   
  12. Text key=new Text();  
  13. Text value=new Text();  
  14. while(reader.next(key,value)){  
  15.     System.out.println(key);  
  16.     System.out.println(value);  
  17. }  
  18. IOUtils.closeStream(reader);//關閉read流  

二、MapFile

MapFile是排序後的SequenceFile,通過觀察其目錄結構可以看到MapFile由兩部分組成,分別是data和index。

index作爲文件的數據索引,主要記錄了每個Record的key值,以及該Record在文件中的偏移位置。在MapFile被訪問的時候,索引文件會被加載到內存,通過索引映射關係可迅速定位到指定Record所在文件位置,因此,相對SequenceFile而言,MapFile的檢索效率是高效的,缺點是會消耗一部分內存來存儲index數據。

需注意的是,MapFile並不會把所有Record都記錄到index中去,默認情況下每隔128條記錄存儲一個索引映射。當然,記錄間隔可人爲修改,通過MapFIle.Writer的setIndexInterval()方法,或修改io.map.index.interval屬性;

另外,與SequenceFile不同的是,MapFile的KeyClass一定要實現WritableComparable接口,即Key值是可比較的。

示例:MapFile讀寫操作

[java]
  1. Configuration conf=new Configuration();  
  2. FileSystem fs=FileSystem.get(conf);  
  3. Path mapFile=new Path("mapFile.map");  
  4. //Reader內部類用於文件的讀取操作   
  5. MapFile.Reader reader=new MapFile.Reader(fs,mapFile.toString(),conf);  
  6. //Writer內部類用於文件的寫操作,假設Key和Value都爲Text類型   
  7. MapFile.Writer writer=new MapFile.Writer(conf,fs,mapFile.toString(),Text.class,Text.class);  
  8. //通過writer向文檔中寫入記錄   
  9. writer.append(new Text("key"),new Text("value"));  
  10. IOUtils.closeStream(writer);//關閉write流   
  11. //通過reader從文檔中讀取記錄   
  12. Text key=new Text();  
  13. Text value=new Text();  
  14. while(reader.next(key,value)){  
  15.     System.out.println(key);  
  16.     System.out.println(key);  
  17. }  
  18. IOUtils.closeStream(reader);//關閉read流  
注意:使用MapFile或SequenceFile雖然可以解決HDFS中小文件的存儲問題,但也有一定侷限性,如:
1.文件不支持複寫操作,不能向已存在的SequenceFile(MapFile)追加存儲記錄
2.當write流不關閉的時候,沒有辦法構造read流。也就是在執行文件寫操作的時候,該文件是不可讀取的

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章