美文网首页
Hadoop 数据压缩和序列化

Hadoop 数据压缩和序列化

作者: wangdy12 | 来源:发表于2017-12-27 20:01 被阅读0次

压缩

文件压缩有两个好处:减少了存储文件所需的空间,并加速数据在网络和磁盘间的传输

常见的压缩格式:


所有的压缩算法都需要在空间和时间上进行权衡,其中splitable表明是否可分,即是否可以搜索数据流的任意位置,并从该位置开始读取数据,可分的数据更适合MapReduce框架处理,如果使用gzip文件作为输入,hadoop通过文件扩展名确定文件不可分,将会使用一个map任务处理所有的数据块,在这种情况下最好在之前的数据处理中,选择合适的数据块大小,将文件切分成块,然后对每个块建立压缩文件

Hadoop 的 codec 算法

通用压缩解压缩算法接口CompressionCodec

public interface CompressionCodec {
  // 对写入的数据进行压缩,输出到out
  CompressionOutputStream createOutputStream(OutputStream out) 
  // 对输入数据流in中的数据进行解压缩
  CompressionInputStream createInputStream(InputStream in) throws IOException;
...
}

public interface SplittableCompressionCodec extends CompressionCodec {
...
  SplitCompressionInputStream createInputStream(InputStream seekableIn,
      Decompressor decompressor, long start, long end, READ_MODE readMode)
      throws IOException;
}

CompressionCodecFactory根据文件名称找到正确的codec

String uri;
Configuration conf = new Configuration();
FileSystem fs = FileSystem.get(URI.create(uri), conf);
Path inputPath = new Path(uri);
CompressionCodecFactory factory = new CompressionCodecFactory(conf);
CompressionCodec codec = factory.getCodec(inputPath);

默认情况下会优先使用native类库实现codec,如果查找不到才会使用纯Java实现的算法

hadoop支持的压缩格式有DEFLATE,gzip,bzip2,LZ4,Snappy,此外还可以通过设定io.compression.codecs设定添加额外的编解码器


串行化

Writable

Hadoop 的序列化格式是Writable,对应接口定义了两个方法,用来将数据写入DataOutput二进制流以及从DataInput二进制流读出状态

package org.apache.hadoop.io;

import java.io.DataOutput;
import java.io.DataInput;
import java.io.IOException;
public interface Writable {
  void write(DataOutput out) throws IOException;
  void readFields(DataInput in) throws IOException;
}

WritableComparable

WritableComparable同时实现WritableComparable接口

public interface WritableComparable<T> extends Writable, Comparable<T> 

类型比较对MapReduce来说是至关重要,因为中间有一个基于键值的排序阶段
任何在Hadoop Map-Reduce框架中用作key的类型都应该实现这个接口

RawComparator是一个优化的比较器,可以直接比较对象的字节流,不需要反序列化

public interface RawComparator<T> extends Comparator<T> {
  public int compare(byte[] b1, int s1, int l1, byte[] b2, int s2, int l2);
}

WritableComparator

WritableComparator是一个比较器,用来比较WritableComparable类型的数据,实现了RawComparator接口,提供compare(byte[],int,int,byte[],int,int)方法,默认方法是反序列化对象,调用对象本身的compareTo方法

可以通过继承WritableComparator对比较函数compare进行重载优化,同时注册相关类对应的比较器define(Class c, WritableComparator comparator),之后可以直接获取WritableComparator get(Class<? extends WritableComparable> c)

Writable 类

Writable 类的层次结构

Java 基本类型

Java 基本类型都有实现Writable接口的包装类型,char类型除外
通过get和set方法读取存储封装的值
int 和 long 类型有对应的变长格式封装,方便节省空间


Text 类型

使用标准UTF-8编码存储文本

索引:指的是编码后字节序列中的位置
getlength:字节的长度
charAt:Unicode编码的一个码点,类似于String的codePointAt方法
find:返回第一个查找到的位置对应的字节偏移量
Unicode

Unicode 字符集
  • 码点 code point : 一个编码表中的某个字符对应的代码值,书写方式 U+后边跟十六进制数字
  • Unicode :字符集,码点从U+0000到U+10FFFF一共21位,1,112,064个码位,分为17个代码级别,第一个平面称为基本多语言平面(Basic Multilingual Plane, BMP),或称第零平面(Plane 0),其他平面称为辅助平面(Supplementary Planes),基本多语言平面内,从U+D800到U+DFFF之间的码位区块永久保留不映射Unicode字符
  • UTF-8:变长编码规则,把Unicode字符集编码为1到4个字节
  • UTF-16:变长编码规则,把Unicode字符集编码为2个或者4个字节,Java的char类型就是UTF-16编码的一个代码单元
UTF-8 UTF-16

BytesWritable

对字节序列的封装,存储格式为字节数目(4 bytes整数字段),后面跟字节内容本身,内容可以通过set方法改变

NullWritable

不可变单例类型,调用NullWritable.get()获取,序列化长度为0,不从数据流中读取,也不写入数据

ObjectWritable / GenericWritable

ObjectWritable是一个通用的封装,用来处理String,arrays,primitive types,null等等,适合用在一个字段有多种数据类型的情况
在Hadoop RPC中,用来封装和解封装方法参数和返回类型
序列化时,每次要写出封装的类名称,更为高效的方法是使用GenericWritable,声明可能需要的类型,用相应的索引来标识类别,消耗一个字节

Writable 集合类

有6个集合类,分别是ArrayWritable, ArrayPrimitiveWritable, TwoDArrayWritable, MapWritable, SortedMapWritable, EnumSetWritable

  • ArrayWritable / TwoDArrayWritable :对应数组和二维数组的Writabe实例
  • ArrayPrimitiveWritable:对Java 基本数据类型和其数组的包装器类,没有涉及底层复制
  • MapWritable /SortedMapWritable:实现java.util.Map<Writable, Writable> / java.util.SortedMap<WritableComparable, Writable>,K/V的类型信息是串行化格式的一部分,占用一个字节,作为对应类型信息的一个索引,可以存放127种自定义的类型,可以使用NullWritable作为V,存储set集合
  • EnumSetWritable:枚举类型

自定义Writable

可以控制二进制表示形式和排序顺序,更好的提升性能
自定义的实现必须有一个默认构造函数,以便 MapReduce 框架可以实例化,并调用readFields填充字段

自定义比较函数器,直接对字节序列进行比较

 //内嵌一个Comparator内部类
public static class Comparator extends WritableComparator{
    public Comparator() {
      super(外部类.class);
    }
    
    @Override
    public int compare(byte[] b1, int s1, int l1,
                       byte[] b2, int s2, int l2) {
        .....例如
      WritableUtils.decodeVIntSize(b1[s1]) //解析vint / vlong的第一个字节来确定字节长度
    }

    @Override
    public int compare(WritableComparable a, WritableComparable b) {
      .... //两种比较方法应该有相同的语义
    }
}
static {
    WritableComparator.define(外部类.class, new Comparator());
}

序列化框架

序列化框架都必须实现org.apache.hadoop.io.serializer.Serialization接口,通过io.serializations属性指定使用的框架,可以通过代码,也可以通过core-default.xml文件指定

默认属性如下:意味着只有Writable 或 Avro 对象可以在外部序列化/反序列化

<property>
    <name>io.serializations</name>
    <value>
        org.apache.hadoop.io.serializer.WritableSerialization,org.apache.hadoop.io.serializer.avro.AvroSpecificSerialization,org.apache.hadoop.io.serializer.avro.AvroReflectSerialization
    </value>
    <source></source>
</property>

另外还提供了一个Java Serialization序列化形式对应的框架org.apache.hadoop.io.serializer.JavaSerialization

相关文章

  • Hadoop 数据压缩和序列化

    压缩 文件压缩有两个好处:减少了存储文件所需的空间,并加速数据在网络和磁盘间的传输 常见的压缩格式: 所有的压缩算...

  • hadoop序列化和反序列化

    hadoop序列化和反序列化 1 什么是序列化和反序列化 序列化就是将内存中的对象或数据,转换成字节数组,以便于存...

  • HADOOP与HDFS数据压缩格式

    HADOOP与HDFS数据压缩格式 1、cloudera 数据压缩的一般准则 一般准则 是否压缩数据以及使用何种压...

  • hadoop(6)序列化

    1 hadoop自己的序列化 因为java中的序列化有太多的冗余信息,所以hadoop采用了自己的序列化机制。 2...

  • Hadoop数据压缩

    4.1 概述 压缩技术能够有效减少底层存储系统(HDFS)读写字节数。压缩提高了网络带宽和磁盘空间的效率。在Had...

  • hadoop 数据压缩

    1. hadoop checknative 可以查看hadoop 支持的压缩算法 2. 启用压缩算法总体来说 节...

  • 2020-12-14

    1。mapper阶段的输入和输出都是kv对2。mapreduce的序列化采用的是hadoop自己的序列化机制:特点...

  • 大数据技术之MapReduce(四)

    Hadoop 数据压缩概述1 )压缩的好处和坏处压缩的优点:以减少磁盘 IO、减少磁盘存储空间。压缩的缺点:增加...

  • MapReduce(二):MapReduce序列化

    序列化概述 什么是序列化 为什么要序列化 为什么不用Java序列化 hadoop序列化优势 结构紧凑,存储空间少 ...

  • Hadoop 之数据压缩

    1 概述 压缩策略和原则 2 MR 支持的压缩编码 为了支持多种压缩/解压缩算法,Hadoop 引入了编码/解码器...

网友评论

      本文标题:Hadoop 数据压缩和序列化

      本文链接:https://www.haomeiwen.com/subject/fgcpgxtx.html