Hadoop Writable机制

《Hadoop技术内幕:深入解析Hadoop Common和HDFS架构设计与实现原理》第3章序列化与压缩,本章涉及了org.apache.hadoop.io包下最重要的两部分内容:序列化和压缩。本节为大家介绍Hadoop Writable机制。

AD:WOT2015 互联网运维与开发者大会 热销抢票

3.1.4 Hadoop Writable机制

为了支持以上这些特性,Hadoop引入org.apache.hadoop.io.Writable接口,作为所有可序列化对象必须实现的接口,其类图如图3-2所示。

Writable机制紧凑、快速(但不容易扩展到Java以外的语言,如C、Python等)。和java.io.Serializable不同,Writable接口不是一个说明性接口,它包含两个方法:

   
   
  1. public interface Writable {  
  2.   /**  
  3.    * 输出(序列化)对象到流中  
  4.    * @param out DataOuput流,序列化的结果保存在流中  
  5.    * @throws IOException  
  6.    */  
  7.   void write(DataOutput out) throws IOException;  
  8.  
  9.  /**  
  10.    * 从流中读取(反序列化)对象  
  11.    * 为了效率,请尽可能复用现有的对象  
  12.    * @param in DataInput流,从该流中读取数据  
  13.    * @throws IOException  
  14.    */  
  15.   void readFields(DataInput in) throws IOException;  
  16. }  

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

   
   
  1. public class Block implements Writable, Comparable<Block>, Serializable {  
  2.   ……  
  3.   private long blockId;  
  4.   private long numBytes;  
  5.   private long generationStamp;  
  6.   ……  
  7.   public void write(DataOutput out) throws IOException {  
  8.      out.writeLong(blockId);  
  9.      out.writeLong(numBytes);  
  10.      out.writeLong(generationStamp);  
  11.   }  
  12.  
  13.  public void readFields(DataInput in) throws IOException {  
  14.      this.blockId = in.readLong();  
  15.      this.numBytes = in.readLong();  
  16.      this.generationStamp = in.readLong();  
  17.      if (numBytes < 0) {  
  18.         throw new IOException("Unexpected block size: " + numBytes);  
  19.      }  
  20.   }  
  21.   ……  
  22. }  

这个例子使用的是前面分析Java序列化机制的Block类,Block实现了Writable接口,即需要实现write()方法和readFields()方法,这两个方法的实现都很简单:Block有三个成员变量,write()方法简单地把这三个变量写入流中,而readFields()则从流中依次读入这些数据,并做必要的检查。

Hadoop序列化机制中还包括另外几个重要接口:WritableComparable、RawComparator和WritableComparator。

WritableComparable,顾名思义,它提供类型比较的能力,这对MapReduce至关重要。该接口继承自Writable接口和Comparable接口,其中Comparable用于进行类型比较。ByteWritable、IntWritable、DoubleWritable等Java基本类型对应的Writable类型,都继承自WritableComparable。

效率在Hadoop中非常重要,因此HadoopI/O包中提供了具有高效比较能力的RawComparator接口。RawComparator和WritableComparable类图如图3-3所示。

 

RawComparator接口允许执行者比较流中读取的未被反序列化为对象的记录,从而省去了创建对象的所有开销。其中,compare()比较时需要的两个参数所对应的记录位于字节数组b1和b2的指定开始位置s1和s1,记录长度为l1和l2,代码如下:

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

以IntWritable为例,它的RawComparator实现中(WritableComparator是一个辅助类,实现了RawComparator接口),compare()方法通过readInt()直接在字节数组中读入需要比较的两个整数,然后输出Comparable接口要求的比较结果。值得注意的是,该过程中compare()方法避免使用IntWritable对象,从而避免了不必要的对象分配。相关代码如下:

   
   
  1. public static class Comparator extends WritableComparator {  
  2.   ……  
  3.   public int compare(byte[] b1, int s1, int l1,  
  4.                      byte[] b2, int s2, int l2) {  
  5.      int thisValue = readInt(b1, s1);  
  6.      int thatValue = readInt(b2, s2);  
  7.      return (thisValue<thatValue ? -1 : (thisValue==thatValue ? 0 : 1));  
  8.   }  
  9.   ……  

WritableComparator是RawComparator对WritableComparable类的一个通用实现。它提供两个主要功能。首先,提供了一个RawComparator的compare()默认实现,该实现从数据流中反序列化要进行比较的对象,然后调用对象的compare()方法进行比较(这些对象都是Comparable的)。其次,它充当了RawComparator实例的一个工厂方法,例如,可以通过如下代码获得IntWritable的RawComparator:

   
   
  1. RawComparator<IntWritable>comparator=  
  2.   WritableComparator.get(IntWritable.class);  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值