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

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

最近在学习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. javaweb 中的过滤器 包装器

    过滤器要做的事情: 请求过滤器:完毕安全检查,又一次格式化请求首部或体.建立请求审计或日志 响应过滤器:     压缩响应流,追加或改动响应流创建一个全然不同的响应. 过滤器和servlet三个相似地 ...

  2. Gas Station,转化为求最大序列的解法,和更简单简单的Jump解法。——贪心、转化

    Gas Station There are N gas stations along a circular route, where the amount of gas at station i is ...

  3. hdu 4858 项目管理(vector模拟)

    # include <stdio.h> # include <algorithm> # include <string.h> # include <vecto ...

  4. android studio 非法字符: &#39;\ufeff&#39; 解决方式

    今天发现一个问题,就是从其它地方拷贝的代码到AS项目里面,木有语法 错误,可是就是执行不起来,老是报错"非法字符: '\ufeff' ",郁闷非常久.木有看到这个字符.最后查询了这 ...

  5. MapReduce简述、工作流程及新旧API对照

    什么是MapReduce? 你想数出一摞牌中有多少张黑桃.直观方式是一张一张检查而且数出有多少张是黑桃. MapReduce方法则是: 1. 给在座的全部玩家中分配这摞牌. 2. 让每一个玩家数自己手 ...

  6. sim的准确识别技术

    几个月钱,我换了一个手机,本着工科男动手能力强的原则,自己用✂️把sim卡剪成了一个小卡,然后成功的可以使用了. 然而就在昨天,我将卡拿出之后,再放回去,却无法识别我的sim卡了. 我上网查了方法,怀 ...

  7. jQuery 工具函数

    jQuery工具函数 一.$.browser对象属性 属性列表 说明 webkit webkit相关浏览器则返回true,否则返回false,如google,傲游. mozilla mozilla相关 ...

  8. 推断php操作mysql(添删改查)是否成功

    近期在使用CI框架 , 可是里面的数据库操作没有ThinkPhp方便 , 不知道数据库操作的反馈信息 , 仅仅好借助原生方法来推断是否操作数据库成功 推断php操作mysql(添删改查)是否成功,主要 ...

  9. 用secureCRT ssh登陆不显示用户名和路径解决方案 分类: 软件工具学习 2015-03-18 16:52 36人阅读 评论(0) 收藏

    方法1         每次开始的时候输入 bash 虽然只能保存一次,但是简便. 方法2 用       vi ~/.bash_profile   编辑这个文件,  有时会提示这个文件不存在,直 ...

  10. 在U-Boot中添加自定义命令以实现自动下载程序【转】

    本文转载自:https://gaomf.cn/2016/06/26/%E5%9C%A8U-Boot%E4%B8%AD%E6%B7%BB%E5%8A%A0%E8%87%AA%E5%AE%9A%E4%B9 ...