HDFS技术之SequenceFile(九)

1. SequenceFile概述

  1. SequenceFile是Hadoop提供的一种对二进制文件的支持,二进制文件直接将<Key, Value>对序列化到文件中。
  2. HDFS文件系统是适合存储大文件的,小文件多的话会对NN造成很大的压力,因为每一个文件都会有一条元数据信息存储在NN上,所以可以通过SequenceFile将小文件合并起来,可以更高效率的存储和计算。
  3. SequenceFile中的key和value可以是任意类型的Writable或者自定义的Writable类型。
  4. SequenceFile文件并不按照其存储的Key进行排序存储,SequenceFile的内部类Writer提供了append功能。
  5. 在存储结构上,SequenceFile主要由一个Header后跟多条Record组成,Header主要包含了,key和value的类名,存储压缩算法,用户自定义元数据等信息。此外,还包含了一些同步标识,用于快速定位到记录的边界。每条Record以键值对的方式进行存储,用来表示它的字符数组可以一次解析成:记录的长度、Key的长度、Key值和value值,并且Value值的结构取决于该记录是否被压缩。

2. SequenceFile优缺点介绍

2.1 SequenceFile优点

2.1.1 支持压缩

  1. 记录(Record)压缩

记录压缩格式与无压缩格式基本相同,不同的是值字节是用定义在头部的编码器来压缩。

  1. 块(Block)压缩

块压缩一次压缩多个记录,因此它比记录压缩更紧凑,而且一般优先选择。当记录的字节数达到最小大小,才会添加到块。该最小值由io.seqfile.compress.blocksize中的属性定义。默认值是1000000字节。格式为记录数、键长度、键、值长度、值。

  1. 无压缩类型

如果没有启动压缩(默认设置),那么每个记录就由它的记录长度(字节数)、键的长度、键和值组成,长度字段为4个字节。

下图为SequenceFile内部结构图:
在这里插入图片描述Record针对压缩,只压缩Value部分不压缩key;Block对Key和Value都压缩。

2.1.2 本地化任务支持

因为文件可以被切分,因此在运行MapReduce任务时数据的本地化情况应该是非常好的,尽可能多地发起Map Task来进行并行处理进而提高作业的执行效率。

2.1.3 难度低

因为Hadoop框架提供API,业务逻辑的修改比较简单。

2.2 SequenceFile缺点

需要一个合并文件的过程,且合并后的文件不方便查看。

3. SequenceFile写操作

3.1 写操作实现步骤

  1. 设置Configuration
  2. 获取FileSystem
  3. 设置文件输出路径
  4. SequenceFile.createWriter()创建SequenceFile.Write写入
  5. 调用SequenceFile.Write.append追加写入
  6. 关闭流

3.2 写操作代码实现

前面提到过的VM options参数,继续设置上。
在这里插入图片描述
代码实现:

package Sequence;


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.Text;

import java.net.URI;


public class SequenceFileWriter {
    private static Configuration configuration = new Configuration();
    private static String HDFS_PATH = "hdfs://master002:9000";
    private static String[] data = {"a,b,c,d,e,f,g","e,f,g,h,j,k","l,m,n,o,p,q,r,s","t,y,v,w,x,y,z"};

    public static void main(String[] args) throws  Exception {
        System.setProperty("HADOOP_USER_NAME", "hadoop");
        FileSystem fileSystem = FileSystem.get(URI.create(HDFS_PATH), configuration);
        Path outputPath = new Path("MySequenceFile.seq");
        IntWritable key = new IntWritable();
        Text value = new Text();

        SequenceFile.Writer writer = SequenceFile.createWriter(fileSystem, configuration,
                outputPath, IntWritable.class, Text.class);

        for(int i=0;i<10;i++){
            key.set(10-i);
            value.set(data[i%data.length]);
            writer.append(key, value);
        }
        IOUtils.closeStream(writer);

    }
}

效果截图:
在这里插入图片描述

4.SequenceFile读操作

4.1 读操作实现步骤

  1. 设置Configuration
  2. 获取FileSystem
  3. 设置文件输出路径
  4. 调用SequenceFile.Reader()创建读取类SequenceFile.Reader
  5. 拿到Key和value的class
  6. 读取
  7. 关闭流

4.2 读操作代码实现

代码实现:

package Sequence;


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.SequenceFile;
import org.apache.hadoop.io.Writable;
import org.apache.hadoop.util.ReflectionUtils;

import java.net.URI;


public class SequenceFileReader {
    private static Configuration configuration = new Configuration();
    private static String HDFS_PATH = "hdfs://master002:9000";

    public static void main(String[] args) throws Exception{
        System.setProperty("HADOOP_USER_NAME", "hadoop");
        FileSystem fileSystem = FileSystem.get(URI.create(HDFS_PATH), configuration);
        Path inputPath = new Path("MySequenceFile.seq");

        SequenceFile.Reader reader = new SequenceFile.Reader(fileSystem, inputPath, configuration);
        Writable keyClass = (Writable) ReflectionUtils.newInstance(reader.getKeyClass(), configuration);
        Writable valueClass = (Writable) ReflectionUtils.newInstance(reader.getValueClass(), configuration);
        while(reader.next(keyClass, valueClass)){
            System.out.println("key:"+keyClass);
            System.out.println("value:"+valueClass);
            System.out.println("position:"+reader.getPosition());
        }
        IOUtils.closeStream(reader);
    }
}

效果截图:
在这里插入图片描述

5. SequenceFile写操作使用压缩

SequenceFile写操作的压缩支持Record和Block两种,在读取时能够自动解压。

代码实现:

package Sequence;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.*;
import org.apache.hadoop.io.compress.BZip2Codec;
import org.apache.hadoop.util.ReflectionUtils;

import java.net.URI;

public class SequenceFileCompression {
    private static Configuration configuration = new Configuration();
    private static String HDFS_PATH = "hdfs://master001:9000";
    private static String[] data = {"a,b,c,d,e,f,g","e,f,g,h,j,k","l,m,n,o,p,q,r,s","t,y,v,w,x,y,z"};

    public static void main(String[] args) throws Exception {
        System.setProperty("HADOOP_USER_NAME", "hadoop");
        FileSystem fileSystem = FileSystem.get(URI.create(HDFS_PATH), configuration);
        Path outputPath = new Path("MySequenceFileCompression.seq");
        IntWritable key = new IntWritable();
        Text value = new Text();

        SequenceFile.Writer writer = SequenceFile.createWriter(fileSystem, configuration, outputPath,
                IntWritable.class, Text.class, SequenceFile.CompressionType.RECORD, new BZip2Codec());

        for(int i=0;i<10;i++){
            key.set(10-i);
            value.set(data[i%data.length]);
            writer.append(key, value);
        }
        IOUtils.closeStream(writer);

        Path inputPath = new Path("MySequenceFileCompression.seq");
        SequenceFile.Reader reader = new SequenceFile.Reader(fileSystem, inputPath, configuration);
        Writable keyClass = (Writable) ReflectionUtils.newInstance(reader.getKeyClass(), configuration);
        Writable valueClass = (Writable)ReflectionUtils.newInstance(reader.getValueClass(), configuration);
        while(reader.next(keyClass, valueClass)){
            System.out.println("key:"+keyClass);
            System.out.println("value:"+valueClass);
            System.out.println("position:"+reader.getPosition());
        }

        IOUtils.closeStream(reader);
    }
}

效果截图:
在这里插入在这里插入图片描述图片描述

在这里插入图片描述

  • 6
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值