此文已由作者肖凡授权网易云社区发布。

欢迎访问网易云社区,了解更多网易技术产品运营经验。

最近在学习hadoop,发现hadoop的序列化过程和jdk的序列化有很大的区别,下面就来说说这两者的区别都有哪些。

1、先简单回顾下JAVA的序列化

JDK的序列化只要实现serializable接口OK了,但是有时需要加上序列化版本ID serialVersionUID ,这是为了:在某些场合,希望类的不同版本对序列化兼容,因此需要确保类的不同版本具有相同的serialVersionUID;而在另外一些场合,不希望类的不同版本对序列化兼容。

java的序列化算法的过程主要如下:

1) 将对象实例相关的类元数据输出。

2) 递归地输出类的超类描述直到不再有超类。

3) 类元数据完了以后,开始从最顶层的超类开始输出对象实例的实际数据值。

4) 从上至下递归输出实例的数据

java的序列化很强大,对于复杂的情形,JAVA序列化机制也能应付自如,所以反序列化就so easy。 但是,Java的序列化机制的缺点也是很明显的,就是计算量开销大,且序列化的结果体积大太,有时能达到对象大小的数倍乃至十倍。它的引用机制也会导致大文件不能分割的问题,比如在一个很大的文件中反序列化某个对象时,需要访问文件中前面的某一个元数据,这将导致整个文件不能被切割,故而不能通过MapReduce来处理。同时,Java序列化会不断的创建新的对象,对于MapReduce应用来说,这将会带来大量的系统开销。这些缺点使得Java的序列化机制对Hadoop来说是不合适的。于是Hadoop设计了自己的序列化机制。

2、hadoop的序列化过程

对于处理大规模数据的Hadoop平台,其序列化机制需要具有如下特征:

1、紧凑:由于带宽是集群中信息传递的最宝贵的资源,所以我们必须想法设法缩小传递信息的大小。

2、快速:在进程间通信时会大量使用序列化机制,因此必须尽量减少序列化和反序列化的开销。

3、对象可重用:JDK的反序列化会不断地创建对象,这肯定会造成一定的系统开销,但是在hadoop的反序列化中,能重复的利用一个对象的readField方法来重新产生不同的对象。     为了支持以上这些特性,hadoo引入了Writeable的接口,作为所有可序列化对象必须实现的接口。Writable机制紧凑、快速,和serializable接口不同,Writable不是一个说明性的接口,它包含两个方法:

public interface Writable {  /** 
   * 输出(序列化)对象到流中
   * 
   * @param out DataOuput 流,序列化的结果保存在流中
   * @throws IOException
   */
  void write(DataOutput out) throws IOException;  /** 
   * 从流中读取(反序列化)对象
   * 为了效率,请尽可能复用现有的对象
   * @param in DataInput流,从该流中读取数据
   * @throws IOException
   */
  void readFields(DataInput in) throws IOException;
}

Writable.write()方法用于将对象状态写入二进制的DataOutput中,反序列化的过程由readFields()从DataInput流中读取状态完成。下面是一个例子:

public class MyWritable implements Writable {	private Text id;	private Text name;	public MyWritable(Text id, Text name) {		super();		this.id = id;		this.name = name;
} public synchronized Text getId() { return id;
} public synchronized void setId(Text id) { this.id = id;
} public synchronized Text getName() { return name;
} public synchronized void setName(Text name) { this.name = name;
} @Override
public void write(DataOutput out) throws IOException {
id.write(out);
name.write(out);
} @Override
public void readFields(DataInput in) throws IOException {
id.readFields(in);
name.readFields(in);
}
}

从上面的例子可以看出,write()和readFields()这两个方法的实现都很简单:MyWritable有两个成员变量,write()方法简单地把这两个成员变量写入流中,而readFields()则从流中依次读入这些数据。目前Java基本类型对应的Writable封装如下表所示:

Java基本类型

Writable

序列化后的长度

boolean

BooleanWritable

1

byte

ByteWritable

1

int

IntWritable

VIntWritable

4

1~5

float

FloatWritable

4

long

LongWritable

VLongWritable

8

1~9

double

DoubleWritable

8

从上表可以看出,对整形(int和long)进行编码的时候,有固定长度格式(IntWritable和LongWritable)和可变长度格式(VIntWritable和VLongWritable)两种选择。固定长度格式的整型,序列化后的数据时定长的,而可变长度格式则使用一种比较灵活的编码方式,对于数值比较小的整型,它们往往比较节省空间,这对于hadoop尤为重要。

3.Hadoop序列化框架

我们知道,大部分的MapReduce程序都使用Writable键-值对作为输入和输出,但这并不是Hadoop的API指定的,其它序列化机制也能够和Hadoop配合使用,目前除了前面提到的JAVA序列化机制和Hadoop使用的Writable机制,还流行其它的序列化框架,如Hadoop Avro、Apache Thrift和Google Protocol Buffer,有兴趣的同学可以去了解下。

Hadoop提供了一个简单的序列化框架API,用于集成各种序列化实现,该框架由Serialization接口实现。通过Serialization可以获得Serializer和Deserializer,分别用来将一个对象转换为一个字节流和将一个字节流转化为一个对象,相关代码如下:

public interface Serialization {  /**
   * 客户端用于判断序列化实现是否支持该类对象
   */
  boolean accept(Class c);  /**
   * 获得用于序列化对象的Serializer实现
   */
  Serializer getSerializer(Class c);  /**
   * 获得用于反序列化对象的Deserializer实现
   */
  Deserializer getDeserializer(Class c);
}

如果需要使用Serializer来执行序列化,一般通过open()方法打开Serializer,open()方法传入一个流对象,然后就可以使用serialize()方法序列化对象到流中,最后序列化结束后,通过close()方法关闭Serializer,相关代码如下:

public interface Serializer {  /**
   * 为输出对象做准备
   */
  void open(OutputStream out) throws IOException; 
  /**
   * 将对象序列化到底层的流中
   */
  void serialize(T t) throws IOException;  /**
   * 序列化结束,清理
   */  
  void close() throws IOException;
}

Hadoop目前支持两个Serialization实现,分别是支持Writable机制的WritableSerialization和支持Java序列化的JavaSerialization。通过JavaSerialization可以再MapReduce程序中使用标准的Java类型,但是这种序列化不如Hadoop的序列化机制有效,非特殊情况不要轻易尝试。

网易云免费体验馆,0成本体验20+款云产品!

更多网易技术、产品、运营经验分享请点击

相关文章:
【推荐】 Spring Cloud使用总结
【推荐】 Java web 服务启动时Xss溢出异常处理笔记
【推荐】 大数据技术在金融行业的应用前景

hadoop中的序列化的更多相关文章

  1. 1 weekend110的复习 + hadoop中的序列化机制 + 流量求和mr程序开发

    以上是,weekend110的yarn的job提交流程源码分析的复习总结 下面呢,来讲weekend110的hadoop中的序列化机制 1363157985066      13726230503  ...

  2. hadoop中的序列化与Writable接口

    本文地址:http://www.cnblogs.com/archimedes/p/hadoop-writable-interface.html,转载请注明源地址. 简介 序列化和反序列化就是结构化对象 ...

  3. hadoop中的序列化与Writable类

    本文地址:http://www.cnblogs.com/archimedes/p/hadoop-writable-class.html,转载请注明源地址. hadoop中自带的org.apache.h ...

  4. 一脸懵逼学习Hadoop中的序列化机制——流量求和统计MapReduce的程序开发案例——流量求和统计排序

    一:序列化概念 序列化(Serialization)是指把结构化对象转化为字节流.反序列化(Deserialization)是序列化的逆过程.即把字节流转回结构化对象.Java序列化(java.io. ...

  5. Hadoop中序列化与Writable接口

    学习笔记,整理自<Hadoop权威指南 第3版> 一.序列化 序列化:序列化是将 内存 中的结构化数据 转化为 能在网络上传输 或 磁盘中进行永久保存的二进制流的过程:反序列化:序列化的逆 ...

  6. Hadoop中客户端和服务器端的方法调用过程

    1.Java动态代理实例 Java 动态代理一个简单的demo:(用以对比Hadoop中的动态代理) Hello接口: public interface Hello { void sayHello(S ...

  7. Hadoop中WritableComparable 和 comparator

    1.WritableComparable 查看HadoopAPI,如图所示: WritableComparable继承自Writable和java.lang.Comparable接口,是一个Writa ...

  8. hadoop文件的序列化

    目录 1.为什么要序列化? 2.什么是序列化? 3.为什么不用Java的序列化? 4.为什么序列化对Hadoop很重要? 5.Hadoop中定义哪些序列化相关的接口呢? 6.Hadoop 自定义Wri ...

  9. Hadoop 中 IPC 的源码分析

    最近开始看 Hadoop 的一些源码,展开hadoop的源码包,各个组件分得比较清楚,于是开始看一下 IPC 的一些源码. IPC模块,也就是进程间通信模块,如果是在不同的机器上,那就可以理解为 RP ...

随机推荐

  1. 【转】How to Change File Ownership & Groups in Linux

    有关linux下 文件权限的问题,一直不是很清楚.(参考菜鸟教程: http://www.runoob.com/linux/linux-file-attr-permission.html) 像上面这样 ...

  2. 一种排序(nyoj8)(简单排序)

    一种排序 时间限制:3000 ms  |  内存限制:65535 KB 难度:3 描写叙述 如今有非常多长方形.每个长方形都有一个编号,这个编号能够反复.还知道这个长方形的宽和长,编号.长.宽都是整数 ...

  3. 线程特定数据TSD总结

    一线程的本质 二线程模型的引入 三线程特定数据 四关键函数说明 五刨根问底啥原理 六私有数据使用演示样例 七參考文档 一.线程的本质 Linux线程又称轻量进程(LWP),也就说线程本质是用进程之间共 ...

  4. LeetCode_3Sum

    一.题目 3Sum Total Accepted: 45112 Total Submissions: 267165My Submissions Given an array S of n intege ...

  5. requirejs中的define

    关于requirejs中的define的原理理解   我们已经了解到模块模式是为单例创建私有变量和特权方法的.一个最基本的例子: var foo=(function(){ var something= ...

  6. Spring Boot与Micronaut性能比较

    文章转载出处:微信公众号——锅外的大佬 链接:https://mp.weixin.qq.com/s/MdBByJ0ju-rROKg7jsWygA 今天我们将比较两个在JVM上构建微服务的框架:Spri ...

  7. Oracle核心技术 笔记(该书读得不细致,须要找时间再细读~~)

    Oracle核心技术 跳转至: 导航. 搜索 文件夹 1 開始 2 redo和undo 3 事务与一致性 4 锁与闩 5 缓存和复制 6 写入和恢复 7 解析与优化 8 RAC及'缺陷' 9 附录A ...

  8. JSP与HTML的差别

    HTML(Hypertext Markup Language)文本标记语言,它是静态页面,和JavaScript一样解释性语言,为什么说是解释性 语言呢?由于.仅仅要你有一个浏览器那么它就能够正常显示 ...

  9. python day- 6 is 和 ==的区别 encode 和 decode

    1.is 和  == 的区别. == 是由来判断左右两边的内容是否相等. is 是用来判断内存地址是否相同. 引进 id (   )函数 小数据池: 对于字符串 ,数字 ,bool 值进行 id()计 ...

  10. compile java sources

    Information:javac 1.8.0_91 was used to compile java sources D:\myjdk\bin\java "-javaagent:C:\Pr ...