Hadoop基於文件的數據結構及實例


基於文件的數據結構
兩種文件格式:
1、SequenceFile
2、MapFile

SequenceFile

1、SequenceFile文件是Hadoop用來存儲二進制形式的<key,value>對而設計的一種平面文件(Flat File)。

2、能夠把SequenceFile當做一個容器,把全部文件打包到SequenceFile類中能夠高效的對小文件進行存儲和處理。

3、SequenceFile文件並不依照其存儲的key進行排序存儲。SequenceFile的內部類Writer**提供了append功能**。

4、SequenceFile中的key和value能夠是隨意類型Writable或者是自己定義Writable類型。

SequenceFile壓縮

1、SequenceFile的內部格式取決於是否啟用壓縮。假設是。要么是記錄壓縮。要么是塊壓縮。
2、三種類型:
A.無壓縮類型:假設沒有啟用壓縮(默認設置),那么每一個記錄就由它的記錄長度(字節數)、鍵的長度。鍵和值組成。長度字段為四字節。

B.記錄壓縮類型:記錄壓縮格式與無壓縮格式基本同樣。不同的是值字節是用定義在頭部的編碼器來壓縮。注意,鍵是不壓縮的。

C.塊壓縮類型:塊壓縮一次壓縮多個記錄。因此它比記錄壓縮更緊湊,並且一般優先選擇

當記錄的字節數達到最小大小,才會加入到塊。

該最小值由io.seqfile.compress.blocksize中的屬性定義。

默認值是1000000字節。

格式為記錄數、鍵長度、鍵、值長度、值。

無壓縮格式與記錄壓縮格式

塊壓縮格式

SequenceFile文件格式的優點
A.支持基於記錄(Record)或塊(Block)的數據壓縮。
B.支持splittable,能夠作為MapReduce的輸入分片。
C.改動簡單:主要負責改動對應的業務邏輯,而不用考慮詳細的存儲格式。


SequenceFile文件格式的壞處
壞處是須要一個合並文件的過程。且合並后的文件將不方便查看。由於它是二進制文件。

讀寫SequenceFile

寫過程:
1)創建Configuration
2)獲取FileSystem
3)創建文件輸出路徑Path
4)調用SequenceFile.createWriter得到SequenceFile.Writer對象
5)調用SequenceFile.Writer.append追加寫入文件
6)關閉流
讀過程:
1)創建Configuration
2)獲取FileSystem
3)創建文件輸出路徑Path
4)new一個SequenceFile.Reader進行讀取
5)得到keyClass和valueClass
6)關閉流

org.apache.hadoop.io 
Class SequenceFile
There are three SequenceFile Writers based on the SequenceFile.CompressionType used to compress key/value pairs: 
1、Writer : Uncompressed records. 
2、RecordCompressWriter : Record-compressed files, only compress values. 
3、BlockCompressWriter : Block-compressed files, both keys & values are collected in 'blocks' separately and compressed. The size of the 'block' is configurable

無壓縮方式、記錄壓縮、塊壓縮實例

package SequenceFile;

import java.io.IOException;
import java.net.URI;


import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IOUtils;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.SequenceFile;
import org.apache.hadoop.io.SequenceFile.CompressionType;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.io.Writable;
import org.apache.hadoop.io.compress.BZip2Codec;
import org.apache.hadoop.util.ReflectionUtils;

public class Demo01 {

    final static String uri= "hdfs://liguodong:8020/liguodong";
    final static String[] data = {
        "apache,software","chinese,good","james,NBA","index,pass"
    };

    public static void main(String[] args) throws IOException {
        //1
        Configuration configuration = new Configuration();
        //2
        FileSystem fs = FileSystem.get(URI.create(uri),configuration);
        //3
        Path path = new Path("/tmp.seq");

        write(fs,configuration,path);
        read(fs,configuration,path);

    }

    public static void write(FileSystem fs,Configuration configuration,Path path) throws IOException{
        //4
        IntWritable key = new IntWritable();
        Text value = new Text();
        //無壓縮
        /*@SuppressWarnings("deprecation") SequenceFile.Writer writer = SequenceFile.createWriter (fs,configuration,path,key.getClass(),value.getClass());*/
        //記錄壓縮
        @SuppressWarnings("deprecation")
        SequenceFile.Writer writer = SequenceFile.createWriter
                (fs,configuration,path,key.getClass(),
                        value.getClass(),CompressionType.RECORD,new BZip2Codec());
        //塊壓縮
        /*@SuppressWarnings("deprecation") SequenceFile.Writer writer = SequenceFile.createWriter (fs,configuration,path,key.getClass(), value.getClass(),CompressionType.BLOCK,new BZip2Codec());*/

        //5
        for (int i = 0; i < 30; i++) {
            key.set(100-i);
            value.set(data[i%data.length]);
            writer.append(key, value);
        }
        //6、關閉流
        IOUtils.closeStream(writer); 
    }

    public static void read(FileSystem fs,Configuration configuration,Path path) throws IOException {
        //4
        @SuppressWarnings("deprecation")
        SequenceFile.Reader reader = new SequenceFile.Reader(fs, path,configuration);
        //5
        Writable key = (Writable) ReflectionUtils.newInstance
                (reader.getKeyClass(), configuration);
        Writable value = (Writable) ReflectionUtils.newInstance
                (reader.getValueClass(), configuration);

        while(reader.next(key,value)){
            System.out.println("key = " + key);
            System.out.println("value = " + value);
            System.out.println("position = "+ reader.getPosition());
        }
        IOUtils.closeStream(reader);
    }
}

執行結果:

key = 100
value = apache,software
position = 164
key = 99
value = chinese,good
position = 197
key = 98
value = james,NBA
position = 227
key = 97
value = index,pass
position = 258
key = 96
value = apache,software
position = 294
key = 95
value = chinese,good
position = 327
......
key = 72
value = apache,software
position = 1074
key = 71
value = chinese,good
position = 1107

MapFile

public class MapFile {
  /** The name of the index file. */
  public static final String INDEX_FILE_NAME = "index";

  /** The name of the data file. */
  public static final String DATA_FILE_NAME = "data";
}

MapFile是經過排序的索引的SequenceFile,能夠依據key進行查找。

與SequenceFile不同的是。 MapFile的Key一定要實現WritableComparable接口 ,即Key值是可比較的,而value是Writable類型的。
能夠使用MapFile.fix()方法來重建索引,把SequenceFile轉換成MapFile。
它有兩個靜態成員變量:

static final String INDEX_FILE_NAME
static final String DATA_FILE_NAME

通過觀察其文件夾結構能夠看到MapFile由兩部分組成,各自是data和index。
index作為文件的數據索引,主要記錄了每一個Record的key值,以及該Record在文件里的偏移位置。

在MapFile被訪問的時候,索引文件會被載入到內存,通過索引映射關系可迅速定位到指定Record所在文件位置。
因此。相對SequenceFile而言, MapFile的檢索效率是高效的。缺點是會消耗一部分內存來存儲index數據。
需注意的是, MapFile並不會把全部Record都記錄到index中去,默認情況下每隔128條記錄存儲一個索引映射。當然,記錄間隔可人為改動,通過MapFIle.Writer的setIndexInterval()方法。或改動io.map.index.interval屬性。

讀寫MapFile

寫過程:
1)創建Configuration
2)獲取FileSystem
3)創建文件輸出路徑Path
4)new一個MapFile.Writer對象
5)調用MapFile.Writer.append追加寫入文件
6)關閉流
讀過程:
1)創建Configuration
2)獲取FileSystem
3)創建文件輸出路徑Path
4)new一個MapFile.Reader進行讀取
5)得到keyClass和valueClass
6)關閉流

詳細操作與SequenceFile類似。

命令行查看二進制文件
hdfs dfs -text /liguodong/tmp.seq


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM