设为首页 收藏本站
查看: 953|回复: 0

[经验分享] Hadoop序列化与Writable接口(一)

[复制链接]

尚未签到

发表于 2017-12-17 18:46:42 | 显示全部楼层 |阅读模式
序列化
  序列化(serialization)是指将结构化的对象转化为字节流,以便在网络上传输或者写入到硬盘进行永久存储;相对的反序列化(deserialization)是指将字节流转回到结构化对象的过程。
  在分布式系统中进程将对象序列化为字节流,通过网络传输到另一进程,另一进程接收到字节流,通过反序列化转回到结构化对象,以达到进程间通信。在Hadoop中,Mapper,Combiner,Reducer等阶段之间的通信都需要使用序列化与反序列化技术。举例来说,Mapper产生的中间结果(<key: value1, value2...>)需要写入到本地硬盘,这是序列化过程(将结构化对象转化为字节流,并写入硬盘),而Reducer阶段读取Mapper的中间结果的过程则是一个反序列化过程(读取硬盘上存储的字节流文件,并转回为结构化对象),需要注意的是,能够在网络上传输的只能是字节流,Mapper的中间结果在不同主机间洗牌时,对象将经历序列化和反序列化两个过程。
  序列化是Hadoop核心的一部分,在Hadoop中,位于org.apache.hadoop.io包中的Writable接口是Hadoop序列化格式的实现。

Writable接口
  Hadoop Writable接口是基于DataInput和DataOutput实现的序列化协议,紧凑(高效使用存储空间),快速(读写数据、序列化与反序列化的开销小)。Hadoop中的键(key)和值(value)必须是实现了Writable接口的对象(键还必须实现WritableComparable,以便进行排序)。
  以下是Hadoop(使用的是Hadoop 1.1.2)中Writable接口的声明:
  

package org.apache.hadoop.io;  

  
import java.io.DataOutput;
  
import java.io.DataInput;
  
import java.io.IOException;
  

  
public interface Writable {
  
  /**
  
   * Serialize the fields of this object to <code>out</code>.
  
   *
  
   * @param out <code>DataOuput</code> to serialize this object into.
  
   * @throws IOException
  
   */
  
  void write(DataOutput out) throws IOException;
  

  
  /**
  
   * Deserialize the fields of this object from <code>in</code>.  
  
   *
  
   * <p>For efficiency, implementations should attempt to re-use storage in the
  
   * existing object where possible.</p>
  
   *
  
   * @param in <code>DataInput</code> to deseriablize this object from.
  
   * @throws IOException
  
   */
  
  void readFields(DataInput in) throws IOException;
  
}
  

  


Writable类
  Hadoop自身提供了多种具体的Writable类,包含了常见的Java基本类型(boolean、byte、short、int、float、long和double等)和集合类型(BytesWritable、ArrayWritable和MapWritable等)。这些类型都位于org.apache.hadoop.io包中。
DSC0000.png

  (图片来源:safaribooksonline.com)

定制Writable类
  虽然Hadoop内建了多种Writable类提供用户选择,Hadoop对Java基本类型的包装Writable类实现的RawComparable接口,使得这些对象不需要反序列化过程,便可以在字节流层面进行排序,从而大大缩短了比较的时间开销,但是当我们需要更加复杂的对象时,Hadoop的内建Writable类就不能满足我们的需求了(需要注意的是Hadoop提供的Writable集合类型并没有实现RawComparable接口,因此也不满足我们的需要),这时我们就需要定制自己的Writable类,特别将其作为键(key)的时候更应该如此,以求达到更高效的存储和快速的比较。
  下面的实例展示了如何定制一个Writable类,一个定制的Writable类首先必须实现Writable或者WritableComparable接口,然后为定制的Writable类编写write(DataOutput out)和readFields(DataInput in)方法,来控制定制的Writable类如何转化为字节流(write方法)和如何从字节流转回为Writable对象。
  

package com.yoyzhou.weibo;  

  
import java.io.DataInput;
  
import java.io.DataOutput;
  
import java.io.IOException;
  
import org.apache.hadoop.io.VLongWritable;
  
import org.apache.hadoop.io.Writable;
  

  
/**

  
*This MyWritable>  
*
  
**/

  
public>  

  

  
private VLongWritable field1;
  
private VLongWritable field2;
  

  
public MyWritable(){
  
this.set(new VLongWritable(), new VLongWritable());
  
}
  

  

  
public MyWritable(VLongWritable fld1, VLongWritable fld2){
  

  
this.set(fld1, fld2);
  

  
}
  

  
public void set(VLongWritable fld1, VLongWritable fld2){
  
//make sure the smaller field is always put as field1
  
if(fld1.get() <= fld2.get()){
  
this.field1 = fld1;
  
this.field2 = fld2;
  
}else{
  

  
this.field1 = fld2;
  
this.field2 = fld1;
  
}
  
}
  

  
//How to write and read MyWritable fields from DataOutput and DataInput stream
  
@Override
  
public void write(DataOutput out) throws IOException {
  

  
field1.write(out);
  
field2.write(out);
  
}
  

  
@Override
  
public void readFields(DataInput in) throws IOException {
  

  
field1.readFields(in);
  
field2.readFields(in);
  
}
  

  
/** Returns true if <code>o</code> is a MyWritable with the same values. */
  
@Override
  
public boolean equals(Object o) {
  
if (!(o instanceof MyWritable))
  
    return false;
  

  
    MyWritable other = (MyWritable)o;
  
    return field1.equals(other.field1) && field2.equals(other.field2);
  

  
}
  

  
@Override
  
public int hashCode(){
  

  
return field1.hashCode() * 163 + field2.hashCode();
  
}
  

  
@Override
  
public String toString() {
  
return field1.toString() + "\t" + field2.toString();
  
}
  

  
}
  

  

  未完待续,下一篇中将介绍Writable对象序列化为字节流时占用的字节长度以及其字节序列的构成。

参考资料
  Tom White, Hadoop: The Definitive Guide, 3rd Edition
  ---To Be Continued---

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-425103-1-1.html 上篇帖子: hadoop Datanode Uuid unassigned 下篇帖子: hadoop集群的搭建(分布式安装)
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表