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

[经验分享] Hadoop 序列化的研究

[复制链接]

尚未签到

发表于 2018-11-1 08:11:04 | 显示全部楼层 |阅读模式
  Hadoop和java自带的序列化机制不同,它自己提供了一组序列化体系接口和类。
  对于基本数据类型,Writable接口就代表了可以被序列化的数据,这个接口定义了2个方法,其中write方法可以吧这个数据序列化到参数给出的DataOutput的字节数组中,而readField方法则可以从DatInput中读取被序列化后的字节数组,并且反序列化为Hadoop数据:
  


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

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

  但是在Hadoop中,序列化过程一般用于Map-Reduce,我们看不到序列化的中间产物。为了捕捉到序列化的轨迹,我们自己写了一个工具方法,让其序列化到字节数组中,这样我们可以把字节数组的内容打印出来得到序列化后的产物:
  


  • /*
  • */
  • package com.charles.hadoop.serial;


  • import java.io.ByteArrayOutputStream;
  • import java.io.DataOutputStream;
  • import java.io.IOException;

  • import org.apache.hadoop.io.Writable;

  • /**
  • *
  • * Description: 这个类提供了工具方法来记录序列化的轨迹
  • * 因为,在hadoop中序列化和反序列化都是在Writable接口中进行的,Writable是被序列化的Hadoop对象
  • * 所以我们把序列化的产物存到字节数组中从而可以捕捉到内容
  • *
  • * @author charles.wang
  • * @created Jun 2, 2012 9:32:41 AM
  • *
  • */
  • public class HadoopSerializationUtil {

  •     //这个方法可以把Hadoop的对象(Writable表示这个是可以序列化的)序列化到字节数组中,
  •     //然后把字节数组中的内容返回出来
  •     //入参,被序列化的数值对象
  •     //返回值:序列化后的字节数组
  •     public static byte[] serialize(Writable writable) throws IOException {
  •         //创建一个字节数组
  •          ByteArrayOutputStream out = new ByteArrayOutputStream();
  •          //创建一个DataOutputStream,并且包装字节数组,用于存放序列化后的字节流
  •          DataOutputStream dataout =  new DataOutputStream(out);
  •          //让Hadoop对象序列化到字节数组对应的字节流中
  •          writable.write(dataout);
  •          dataout.close();
  •          //返回序列化后的字节流
  •          return out.toByteArray();
  •     }



  • }
  

  为了显示序列化前的Hadoop基本数据值和序列化后的字节数组,我们写了另一个工具类,这个工具类可以在包装序列化前后的信息到字符串对象中:
  


  • /*
  • */
  • package com.charles.hadoop.serial;

  • import org.apache.hadoop.io.BooleanWritable;
  • import org.apache.hadoop.io.ByteWritable;
  • import org.apache.hadoop.io.DoubleWritable;
  • import org.apache.hadoop.io.FloatWritable;
  • import org.apache.hadoop.io.IntWritable;
  • import org.apache.hadoop.io.LongWritable;
  • import org.apache.hadoop.io.Writable;
  • import org.apache.hadoop.util.StringUtils;

  • /**
  • *
  • * Description: 这个工具类用于帮助我们做实验,
  • * 它可以在封装序列化前的基本数据类型值和序列化后的字节数组的内容到字符串对象中
  • *
  • * @author charles.wang
  • * @created Jun 2, 2012 9:58:44 AM
  • *
  • */
  • public class HadoopExperimentUtil {

  •     public static String displaySerializationExperimentResult(Writable writable) throws Exception{

  •         String typeInfo = null;
  •         String primaryValueInfo = null;
  •         byte[] serializedHadoopValue = null;
  •         String lengthInfo = null;
  •         String serializeValueInfo = null;

  • //获取参数对象的类名
  •         String className=writable.getClass().getName();


  •         if(className.equals("org.apache.hadoop.io.BooleanWritable")){
  •             typeInfo = "被测试的Hadoop类型为: " + "org.apache.hadoop.io.BooleanWritable" +"\n";
  •             primaryValueInfo = "初始值为: "+((BooleanWritable)writable).get()+"\n";
  •         }

  •         else if(className.equals("org.apache.hadoop.io.ByteWritable")){
  •             typeInfo = "被测试的Hadoop类型为: " + "org.apache.hadoop.io.ByteWritable" +"\n";
  •             primaryValueInfo = "初始值为: "+((ByteWritable)writable).get()+"\n";
  •         }

  •         else if(className.equals("org.apache.hadoop.io.IntWritable")){
  •         typeInfo = "被测试的Hadoop类型为: " + "org.apache.hadoop.io.IntWritable" +"\n";
  •         primaryValueInfo = "初始值为: "+((IntWritable)writable).get()+"\n";
  •         }

  •         else if(className.equals("org.apache.hadoop.io.FloatWritable")){
  •             typeInfo = "被测试的Hadoop类型为: " + "org.apache.hadoop.io.FloatWritable" +"\n";
  •             primaryValueInfo = "初始值为: "+((FloatWritable)writable).get()+"\n";
  •             }

  •         else if(className.equals("org.apache.hadoop.io.LongWritable")){
  •             typeInfo = "被测试的Hadoop类型为: " + "org.apache.hadoop.io.LongWritable" +"\n";
  •             primaryValueInfo = "初始值为: "+((LongWritable)writable).get()+"\n";
  •             }

  •         else if(className.equals("org.apache.hadoop.io.DoubleWritable")){
  •             typeInfo = "被测试的Hadoop类型为: " + "org.apache.hadoop.io.DoubleWritable" +"\n";
  •             primaryValueInfo = "初始值为: "+((DoubleWritable)writable).get()+"\n";
  •             }


  •         //使用我们自定义的工具类方法,这个方法最终会调用Writable接口的write方法执行序列化动作
  •         serializedHadoopValue =HadoopSerializationUtil.serialize(writable);
  • //获取序列化后的自己数组的长度信息
  •         lengthInfo= "序列化后的字节数组长度为: "+serializedHadoopValue.length+"\n";
  • //使用hadoop的StringUtils工具类来读取以16进制显示的字节数组的值
  •         serializeValueInfo= "序列化后的值为: " +StringUtils.byteToHexString(serializedHadoopValue)+"\n";


  •         //返回全部信息
  •         return "\n"+typeInfo+primaryValueInfo+lengthInfo+serializeValueInfo+"\n";


  •     }
  • }
  

  最终,我们还需要一个实验类,我们传入各种Hadoop数据对象(都要是Writable的),然后我们依次调用实验工具类的方法,最终把这些序列化过程前后的信息打印在控制台上:
  


  • /*
  • */
  • package com.charles.hadoop.serial;

  • import org.apache.hadoop.io.BooleanWritable;
  • import org.apache.hadoop.io.ByteWritable;
  • import org.apache.hadoop.io.DoubleWritable;
  • import org.apache.hadoop.io.FloatWritable;
  • import org.apache.hadoop.io.IntWritable;
  • import org.apache.hadoop.io.LongWritable;

  • /**
  • *
  • * Description: 这里做实验
  • *
  • * @author charles.wang
  • * @created Jun 2, 2012 9:43:57 AM
  • *
  • */
  • public class HadoopSerializationMain {

  •     /**
  •      * @param args
  •      */
  •     public static void main(String[] args) throws Exception {

  •           BooleanWritable hadoopBooleanValue = new BooleanWritable(false);
  •           System.out.println(HadoopExperimentUtil.displaySerializationExperimentResult(hadoopBooleanValue));

  •           byte b = 3&0x0f;
  •           ByteWritable hadoopByteValue = new ByteWritable(b);
  •           System.out.println(HadoopExperimentUtil.displaySerializationExperimentResult(hadoopByteValue));

  •           IntWritable hadoopIntValue = new IntWritable(100);
  •           System.out.println(HadoopExperimentUtil.displaySerializationExperimentResult(hadoopIntValue) );

  •           FloatWritable hadoopFloatValue = new FloatWritable(73.54f);
  •           System.out.println(HadoopExperimentUtil.displaySerializationExperimentResult(hadoopFloatValue) );

  •           LongWritable hadoopLongValue = new LongWritable(82l);
  •           System.out.println(HadoopExperimentUtil.displaySerializationExperimentResult(hadoopLongValue) );

  •           DoubleWritable hadoopDoubleValue = new DoubleWritable(100.302d);
  •           System.out.println(HadoopExperimentUtil.displaySerializationExperimentResult(hadoopDoubleValue) );
  •     }

  • }
  

  最终控制台显示如下:
  


  • 被测试的Hadoop类型为: org.apache.hadoop.io.BooleanWritable
  • 初始值为: false
  • 序列化后的字节数组长度为: 1
  • 序列化后的值为: 00



  • 被测试的Hadoop类型为: org.apache.hadoop.io.ByteWritable
  • 初始值为: 3
  • 序列化后的字节数组长度为: 1
  • 序列化后的值为: 03



  • 被测试的Hadoop类型为: org.apache.hadoop.io.IntWritable
  • 初始值为: 100
  • 序列化后的字节数组长度为: 4
  • 序列化后的值为: 00000064



  • 被测试的Hadoop类型为: org.apache.hadoop.io.FloatWritable
  • 初始值为: 73.54
  • 序列化后的字节数组长度为: 4
  • 序列化后的值为: 4293147b



  • 被测试的Hadoop类型为: org.apache.hadoop.io.LongWritable
  • 初始值为: 82
  • 序列化后的字节数组长度为: 8
  • 序列化后的值为: 0000000000000052



  • 被测试的Hadoop类型为: org.apache.hadoop.io.DoubleWritable
  • 初始值为: 100.302
  • 序列化后的字节数组长度为: 8
  • 序列化后的值为: 40591353f7ced917
  

  我们从实验结果不难看出,Hadoop的序列化后的字节数组的长度和Java基本类型本身占用的字节数是完全匹配的。



运维网声明 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-629141-1-1.html 上篇帖子: Hadoop 2.0.0-alpha尝鲜安装和hello world 下篇帖子: 自定义Hadoop的可序列化类
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

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

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

扫描微信二维码查看详情

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


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


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


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



合作伙伴: 青云cloud

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