Hadoop序列化机制及实例

标签: hadoop 序列化 实例 | 发表时间:2015-06-07 01:01 | 作者:scgaliguodong123_
出处:http://blog.csdn.net

序列化

1、什么是序列化?
将结构化对象转换成字节流以便于进行网络传输或写入持久存储的过程。
2、什么是反序列化?
将字节流转换为一系列结构化对象的过程。

序列化 用途

1、作为一种 持久化格式
2、作为一种 通信的数据格式
3、作为一种数据拷贝、克隆机制。

Java序列化和反序列化

1、创建一个对象实现了 Serializable
2、序列化: ObjectOutputStream.writeObject(序列化对象)
反序列化: ObjectInputStream.readObject()返回序列化对象
具体实现,可参考如下文章:
http://blog.csdn.net/scgaliguodong123_/article/details/45938555

为什么Hadoop不直接使用java序列化?

Hadoop的序列化机制与java的序列化机制不同,它将对象序列化到流中,值得一提的是java的序列化机制是不断的创建对象,但在Hadoop的序列化机制中,用户可以复用对象,这样就减少了java对象的分配和回收,提高了应用效率。

Hadoop序列化

Hadoop的序列化不采用java的序列化,而是实现了自己的序列化机制。
Hadoop通过 Writable接口实现的序列化机制,不过没有提供比较功能,所以和java中的 Comparable接口合并,提供一个接口 WritableComparable。(自定义比较)

Writable接口提供两个方法(write和readFields)。

  package org.apache.hadoop.io;
public interface Writable {
  void write(DataOutput out) throws IOException;
  void readFields(DataInput in) throws IOException;
}

需要进行比较的话,要实现WritableComparable接口。

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

比如mapreduce中需要对key值进行相应的排序。可参考下面的例子:
http://blog.csdn.net/scgaliguodong123_/article/details/46010947

Hadoop提供了几个重要的序列化接口与实现类:

外部集合的比较器

RawComparator<T>、WritableComparator

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

public class WritableComparator implements RawComparator {
  private final Class<? extends WritableComparable> keyClass;
  private final WritableComparable key1;
  private final WritableComparable key2;
}

实现了WritableComparable接口的类(自定义比较)

  org.apache.hadoop.io 
接口
WritableComparable<T>
父接口
Comparable<T>, Writable 
基础实现类
BooleanWritable, ByteWritable, ShortWritable,IntWritable,
VIntWritable,LongWritable, VLongWritable , FloatWritable, DoubleWritable
高级实现类
MD5Hash, NullWritable,Text, BytesWritable,ObjectWritable,GenericWritable

仅实现了Writable接口的类

  org.apache.hadoop.io 
Interface(接口) Writable
All Known Subinterfaces(子接口): 
Counter, CounterGroup, CounterGroupBase<T>, InputSplit, InputSplitWithLocationInfo, WritableComparable<T> 

仅实现了Writable接口的类
数组:AbstractWritable、TwoDArrayWritable
映射:AbstractMapWritable、MapWritable、SortedMapWritable


Writable接口


Text
Text是UTF-8的Writable,可以理解为java.lang.String相类似的Writable。Text类替代了UTF-8类。Text是可变的,其值可以通过调用set()方法改变。最大可以存储2GB的大小。

NullWritable
NullWritable是一种特殊的Writable类型,它的序列化长度为零,可以用作占位符。

BytesWritable
BytesWritable是一个二进制数据数组封装,序列化格式是一个int字段。
例如:一个长度为2,值为3和5的字节数组序列后的结果是:

  @Test  
public void testByteWritableSerilizedFromat() throws IOException {  
    BytesWritable bytesWritable=new BytesWritable(new byte[]{3,5});  
    byte[] bytes=SerializeUtils.serialize(bytesWritable);
    Assert.assertEquals(StringUtils.byteToHexString(bytes),"000000020305"); //true
}  

BytesWritable是可变的,其值可以通过调用set()方法来改变。

ObjectWritable
ObjectWritable适用于字段使用多种类型时。

Writable集合
1、 ArrayWritableTwoDArrayWritable是针对数组和二维数组。
2、 MapWritableSortedMapWritable是针对Map和SortMap。

自定义Writable

1、实现WritableComparable接口
2、实现相应的 接口方法
A.write() //将对象转换为字节流并写入到输出流out中。
B.readFileds() //从输入流in中读取字节流并发序列化为对象。
C.compareTo(o) //将this对象和对象o进行比较。
可参考下面的例子,自定义NewK2类:
http://blog.csdn.net/scgaliguodong123_/article/details/46010947

  package Writable;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataInput;
import java.io.DataInputStream;
import java.io.DataOutput;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.io.WritableComparable;

public class DefineWritable {
    public static void main(String[] args) throws IOException {
        Student student = new Student("liguodong", 22, "男");
        BufferedOutputStream bos = new BufferedOutputStream(
                new FileOutputStream(new File("g:/liguodong.txt")));
        DataOutputStream dos = new DataOutputStream(bos);
        student.write(dos);
        dos.flush();
        dos.close();
        bos.close();

        Student student2 = new Student();
        BufferedInputStream bis = new BufferedInputStream(
                new FileInputStream(new File("g:/liguodong.txt")));
        DataInputStream dis = new DataInputStream(bis);
        student2.readFields(dis);
        System.out.println("name="+student2.getName()
                +",age="+student2.getAge()+",sex="+student2.getSex());

    }


}


class Student implements WritableComparable<Student>{
    private Text name = new Text();
    private IntWritable age = new IntWritable();
    private Text sex = new Text();

    public Student() {
    }

    public Student(String name, int age, String sex) {
        super();
        this.name = new Text(name);
        this.age = new IntWritable(age);
        this.sex = new Text(sex);
    }

    public Text getName() {
        return name;
    }

    public void setName(Text name) {
        this.name = name;
    }

    public IntWritable getAge() {
        return age;
    }

    public void setAge(IntWritable age) {
        this.age = age;
    }

    public Text getSex() {
        return sex;
    }

    public void setSex(Text sex) {
        this.sex = sex;
    }

    @Override
    public void write(DataOutput out) throws IOException {
        name.write(out);
        age.write(out);
        sex.write(out);
    }

    @Override
    public void readFields(DataInput in) throws IOException {
        //如果使用Java数据类型,比如String name; 
        //this.name = in.readUTF();只能使用这种类型。
        name.readFields(in);
        age.readFields(in);
        sex.readFields(in);

    }

    @Override
    public int compareTo(Student o) {   
        int result=0;
        if((result=this.name.compareTo(o.getName())) != 0 ){
            return result;
        }
        if((result=this.age.compareTo(o.getAge())) != 0 ){
            return result;
        }
        if((result=this.sex.compareTo(o.getSex())) != 0 ){
            return result;
        }
        return 0;
    }

}

运行结果:

  name=liguodong,age=22,sex=男

Hadoop序列化 优势:

1、紧凑:Hadoop中最稀缺的资源是宽带,所以紧凑的序列化机制可以 充分的利用宽带
2、快速:通信时大量使用序列化机制,因此,需要减少序列化和反序列化的开销。
3、可扩展:随着通信协议的升级而可升级。
4、互操作:支持不同开发语言的通信。
Hadoop1.x 序列化仅满足了紧凑和快速的特点。

序列化框架

Apache Avro
1、 丰富的数据结构类型
2、快速可压缩的 二进制数据形式
3、存储持久数据的文件容器
4、 远程过程调用RPC
5、 简单的动态语言结合功能,Avro和动态语言结合后,读写数据文件和使用RPC协议都 不需要生成代码,而 代码生成作为一种可选的优化,只值得在静态类型语言中实现。

Facebook Thrift
1、是一种 可伸缩的跨语言服务的发展软件框架
2、它结合了功能强大的 软件堆栈的代码生成引擎,以建设服务,工作效率和无缝地与C++,C#,.Java,Python和PHP和Ruby结合。
3、允许定义一个简单的定义文件中的数据类型和服务接口,以作为输入文件,编
译器生成代码用来 方便地生成RPC客户端和服务器通信的无缝跨编程语言。

Google Protocolbuffer
PB是Google开源的一种轻量级的结构化数据存储格式,可以用于结构化数据的序
列化与反序列化,很 适合做数据存储RPC数据交换格式
优点:
与 XML相比,它 更小、更快、也更简单。你可以定义自己的数据结构,然后使用代码生成器生成的代码来读写这个数据结构。你甚至可以在 无需重新部署程序的情况下更新数据结构。 只需使用 Protobuf 对数据结构进行一次描述,即可利用各种不同语言或从各种不同数据流中对你的结构化数据轻松读写。

它有一个非常棒的特性,即 “向后”兼容性好,人们不必破坏已部署的、依靠”老”数据格式的程序就可以对数据结构进行升级。这样您的程序就可以不必担心因为消息结构的改变而造成的大规模的代码重构或者迁移的问题。因为添加新的消息中的 field 并不会引起已经发布的程序的任何改变。

Protocolbuffer语义更清晰无需类似 XML 解析器的东西(因为 Protobuf 编译器会将 .proto 文件编译生成对应的数据访问类以对 Protobuf 数据进行序列化、反序列化操作)。使用 Protobuf 无需学习复杂的文档对象模型,Protobuf 的编程模式比较友好,简单易学,同时它拥有良好的文档和示例,对于喜欢简单事物的人们而言,Protobuf 比其他的技术更加有吸引力。

不足:
Protbuf 与 XML 相比也有不足之处。它功能简单, 无法用来表示复杂的概念

由于文本 并不适合用来描述数据结构,所以 Protobuf 也不适合用来对基于文本的标记文档(如 HTML)建模。另外,由于 XML 具有某种程度上的自解释性,它可以被人直接读取编辑,在这一点上 Protobuf 不行,它以二进制的方式存储,除非你有 .proto 定义,否则你没法直接读出 Protobuf 的任何内容。

Hadoop2.X用到的Protocolbuffer
hadoop-2.6.0-src/hadoop-hdfs-project/hadoop-hdfs/src/main/proto

作者:scgaliguodong123_ 发表于2015/6/6 17:01:05 原文链接
阅读:8 评论:0 查看评论

相关 [hadoop 序列化 实例] 推荐:

Hadoop序列化机制及实例

- - CSDN博客推荐文章
将结构化对象转换成字节流以便于进行网络传输或写入持久存储的过程. 将字节流转换为一系列结构化对象的过程. 1、作为一种 持久化格式. 2、作为一种 通信的数据格式. 3、作为一种数据拷贝、克隆机制. Java序列化和反序列化. 1、创建一个对象实现了 Serializable. 2、序列化: ObjectOutputStream.writeObject(序列化对象).

java序列化与反序列化以及浅谈一下hadoop的序列化

- - CSDN博客云计算推荐文章
1、什么是序列化和反序列化. 神马是序列化呢,序列化就是把 内存中的对象的状态信息,转换成 字节序列以便于存储(持久化)和网络传输. (网络传输和硬盘持久化,你没有一定的手段来进行辨别这些字节序列是什么东西,有什么信息,这些字节序列就是垃圾). 反序列化就是将收到 字节序列或者是硬盘的持久化数据,转换成 内存中的对象.

hadoop实例---多表关联

- - CSDN博客研发管理推荐文章
多表关联和单表关联类似,它也是通过对原始数据进行一定的处理,从其中挖掘出关心的信息. 输入的是两个文件,一个代表工厂表,包含工厂名列和地址编号列;另一个代表地址表,包含地址名列和地址编号列. 要求从输入数据中找出工厂名和地址名的对应关系,输出工厂名-地址名表. factoryname addressed Beijing Red Star 1 Shenzhen Thunder 3 Guangzhou Honda 2 Beijing Rising 1 Guangzhou Development Bank 2 Tencent 3 Back of Beijing 1.

大数据框架hadoop的序列化机制

- - ITeye博客
       对象的序列化(Serialization)用于将对象编码成一个字节流,以及从字节流中重新构建对象. “将一个对象编码成一个字节流”称为序列化该对象(Serializing);相反的处理过程称为反序列化(Deserializing). 1.1              Java内建序列化机制.

(反)序列化

- - Java - 编程语言 - ITeye博客
本章关注对象序列化API,它提供了一个框架,用来将对象编码成字节流,并从字节流中重新构建对象. “将对象编码成字节流”被称作对象序列化,相反的处理过程被称作反序列化. 序列化技术为远程通信提供了标准的线路级对象表示法,也为JavaBeans组件结构提供了标准的持久化数据格式. 第七十四条:谨慎地实现Serializable接口.

Hadoop Streaming 编程

- - 学着站在巨人的肩膀上
Hadoop Streaming是Hadoop提供的一个编程工具,它允许用户使用任何可执行文件或者脚本文件作为Mapper和Reducer,例如:. 采用shell脚本语言中的一些命令作为mapper和reducer(cat作为mapper,wc作为reducer). 本文安排如下,第二节介绍Hadoop Streaming的原理,第三节介绍Hadoop Streaming的使用方法,第四节介绍Hadoop Streaming的程序编写方法,在这一节中,用C++、C、shell脚本 和python实现了WordCount作业,第五节总结了常见的问题.

Hadoop使用(一)

- Pei - 博客园-首页原创精华区
Hadoop使用主/从(Master/Slave)架构,主要角色有NameNode,DataNode,secondary NameNode,JobTracker,TaskTracker组成. 其中NameNode,secondary NameNode,JobTracker运行在Master节点上,DataNode和TaskTracker运行在Slave节点上.

Hadoop MapReduce技巧

- - 简单文本
我在使用Hadoop编写MapReduce程序时,遇到了一些问题,通过在Google上查询资料,并结合自己对Hadoop的理解,逐一解决了这些问题. Hadoop对MapReduce中Key与Value的类型是有要求的,简单说来,这些类型必须支持Hadoop的序列化. 为了提高序列化的性能,Hadoop还为Java中常见的基本类型提供了相应地支持序列化的类型,如IntWritable,LongWritable,并为String类型提供了Text类型.

Hadoop TaskScheduler浅析

- - kouu&#39;s home
TaskScheduler,顾名思义,就是MapReduce中的任务调度器. 在MapReduce中,JobTracker接收JobClient提交的Job,将它们按InputFormat的划分以及其他相关配置,生成若干个Map和Reduce任务. 然后,当一个TaskTracker通过心跳告知JobTracker自己还有空闲的任务Slot时,JobTracker就会向其分派任务.

HADOOP安装

- - OracleDBA Blog---三少个人自留地
最近有时间看看hadoop的一些东西,而且在测试的环境上做了一些搭建的工作. 首先,安装前需要做一些准备工作. 使用一台pcserver作为测试服务器,同时使用Oracle VM VirtualBox来作为虚拟机的服务器. 新建了三个虚拟机以后,安装linux,我安装的linux的版本是redhat linux 5.4 x64版本.