Hadoop 序列化的研究

简介:

 Hadoop和java自带的序列化机制不同,它自己提供了一组序列化体系接口和类。

对于基本数据类型,Writable接口就代表了可以被序列化的数据,这个接口定义了2个方法,其中write方法可以吧这个数据序列化到参数给出的DataOutput的字节数组中,而readField方法则可以从DatInput中读取被序列化后的字节数组,并且反序列化为Hadoop数据:

 
 
  1. public interface Writable { 
  2.   /**  
  3.    * Serialize the fields of this object to <code>out</code>. 
  4.    *  
  5.    * @param out <code>DataOuput</code> to serialize this object into. 
  6.    * @throws IOException 
  7.    */ 
  8.   void write(DataOutput out) throws IOException; 
  9.  
  10.   /**  
  11.    * Deserialize the fields of this object from <code>in</code>.   
  12.    *  
  13.    * <p>For efficiency, implementations should attempt to re-use storage in the  
  14.    * existing object where possible.</p> 
  15.    *  
  16.    * @param in <code>DataInput</code> to deseriablize this object from. 
  17.    * @throws IOException 
  18.    */ 
  19.   void readFields(DataInput in) throws IOException; 

 

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

 
 
  1. /*  
  2.  */ 
  3. package com.charles.hadoop.serial; 
  4.  
  5.  
  6. import java.io.ByteArrayOutputStream; 
  7. import java.io.DataOutputStream; 
  8. import java.io.IOException; 
  9.  
  10. import org.apache.hadoop.io.Writable; 
  11.  
  12. /** 
  13.  * 
  14.  * Description: 这个类提供了工具方法来记录序列化的轨迹 
  15.  * 因为,在hadoop中序列化和反序列化都是在Writable接口中进行的,Writable是被序列化的Hadoop对象 
  16.  * 所以我们把序列化的产物存到字节数组中从而可以捕捉到内容 
  17.  * 
  18.  * @author charles.wang 
  19.  * @created Jun 2, 2012 9:32:41 AM 
  20.  *  
  21.  */ 
  22. public class HadoopSerializationUtil { 
  23.      
  24.     //这个方法可以把Hadoop的对象(Writable表示这个是可以序列化的)序列化到字节数组中, 
  25.     //然后把字节数组中的内容返回出来 
  26.     //入参,被序列化的数值对象 
  27.     //返回值:序列化后的字节数组
  28.     public static byte[] serialize(Writable writable) throws IOException { 
  29.         //创建一个字节数组 
  30.          ByteArrayOutputStream out = new ByteArrayOutputStream(); 
  31.          //创建一个DataOutputStream,并且包装字节数组,用于存放序列化后的字节流 
  32.          DataOutputStream dataout =  new DataOutputStream(out); 
  33.          //让Hadoop对象序列化到字节数组对应的字节流中 
  34.          writable.write(dataout); 
  35.          dataout.close(); 
  36.          //返回序列化后的字节流 
  37.          return out.toByteArray(); 
  38.     } 
  39.      
  40.   
  41.  

 

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

 
 
  1. /*  
  2.  */ 
  3. package com.charles.hadoop.serial; 
  4.  
  5. import org.apache.hadoop.io.BooleanWritable; 
  6. import org.apache.hadoop.io.ByteWritable; 
  7. import org.apache.hadoop.io.DoubleWritable; 
  8. import org.apache.hadoop.io.FloatWritable; 
  9. import org.apache.hadoop.io.IntWritable; 
  10. import org.apache.hadoop.io.LongWritable; 
  11. import org.apache.hadoop.io.Writable; 
  12. import org.apache.hadoop.util.StringUtils; 
  13.  
  14. /** 
  15.  * 
  16.  * Description: 这个工具类用于帮助我们做实验, 
  17.  * 它可以在封装序列化前的基本数据类型值和序列化后的字节数组的内容到字符串对象中 
  18.  * 
  19.  * @author charles.wang 
  20.  * @created Jun 2, 2012 9:58:44 AM 
  21.  *  
  22.  */ 
  23. public class HadoopExperimentUtil { 
  24.  
  25.     public static String displaySerializationExperimentResult(Writable writable) throws Exception{ 
  26.          
  27.         String typeInfo = null
  28.         String primaryValueInfo = null
  29.         byte[] serializedHadoopValue = null
  30.         String lengthInfo = null
  31.         String serializeValueInfo = null
  32.         
  33. //获取参数对象的类名
  34.         String className=writable.getClass().getName(); 
  35.  
  36.  
  37.         if(className.equals("org.apache.hadoop.io.BooleanWritable")){ 
  38.             typeInfo = "被测试的Hadoop类型为: " + "org.apache.hadoop.io.BooleanWritable" +"\n"
  39.             primaryValueInfo = "初始值为: "+((BooleanWritable)writable).get()+"\n";        
  40.         } 
  41.          
  42.         else if(className.equals("org.apache.hadoop.io.ByteWritable")){ 
  43.             typeInfo = "被测试的Hadoop类型为: " + "org.apache.hadoop.io.ByteWritable" +"\n"
  44.             primaryValueInfo = "初始值为: "+((ByteWritable)writable).get()+"\n";        
  45.         } 
  46.          
  47.         else if(className.equals("org.apache.hadoop.io.IntWritable")){ 
  48.         typeInfo = "被测试的Hadoop类型为: " + "org.apache.hadoop.io.IntWritable" +"\n"
  49.         primaryValueInfo = "初始值为: "+((IntWritable)writable).get()+"\n";        
  50.         } 
  51.          
  52.         else if(className.equals("org.apache.hadoop.io.FloatWritable")){ 
  53.             typeInfo = "被测试的Hadoop类型为: " + "org.apache.hadoop.io.FloatWritable" +"\n"
  54.             primaryValueInfo = "初始值为: "+((FloatWritable)writable).get()+"\n";        
  55.             } 
  56.          
  57.         else if(className.equals("org.apache.hadoop.io.LongWritable")){ 
  58.             typeInfo = "被测试的Hadoop类型为: " + "org.apache.hadoop.io.LongWritable" +"\n"
  59.             primaryValueInfo = "初始值为: "+((LongWritable)writable).get()+"\n";        
  60.             } 
  61.          
  62.         else if(className.equals("org.apache.hadoop.io.DoubleWritable")){ 
  63.             typeInfo = "被测试的Hadoop类型为: " + "org.apache.hadoop.io.DoubleWritable" +"\n"
  64.             primaryValueInfo = "初始值为: "+((DoubleWritable)writable).get()+"\n";        
  65.             } 
  66.          
  67.          
  68.         //使用我们自定义的工具类方法,这个方法最终会调用Writable接口的write方法执行序列化动作
  69.         serializedHadoopValue =HadoopSerializationUtil.serialize(writable); 
  70. //获取序列化后的自己数组的长度信息
  71.         lengthInfo= "序列化后的字节数组长度为: "+serializedHadoopValue.length+"\n"
  72. //使用hadoop的StringUtils工具类来读取以16进制显示的字节数组的值
  73.         serializeValueInfo= "序列化后的值为: " +StringUtils.byteToHexString(serializedHadoopValue)+"\n"
  74.          
  75.          
  76.         //返回全部信息
  77.         return "\n"+typeInfo+primaryValueInfo+lengthInfo+serializeValueInfo+"\n"
  78.          
  79.         
  80.     } 

 

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

 
 
  1. /*  
  2.  */ 
  3. package com.charles.hadoop.serial; 
  4.  
  5. import org.apache.hadoop.io.BooleanWritable; 
  6. import org.apache.hadoop.io.ByteWritable; 
  7. import org.apache.hadoop.io.DoubleWritable; 
  8. import org.apache.hadoop.io.FloatWritable; 
  9. import org.apache.hadoop.io.IntWritable; 
  10. import org.apache.hadoop.io.LongWritable; 
  11.  
  12. /** 
  13.  * 
  14.  * Description: 这里做实验 
  15.  * 
  16.  * @author charles.wang 
  17.  * @created Jun 2, 2012 9:43:57 AM 
  18.  *  
  19.  */ 
  20. public class HadoopSerializationMain { 
  21.  
  22.     /** 
  23.      * @param args 
  24.      */ 
  25.     public static void main(String[] args) throws Exception { 
  26.          
  27.           BooleanWritable hadoopBooleanValue = new BooleanWritable(false); 
  28.           System.out.println(HadoopExperimentUtil.displaySerializationExperimentResult(hadoopBooleanValue)); 
  29.            
  30.           byte b = 3&0x0f
  31.           ByteWritable hadoopByteValue = new ByteWritable(b); 
  32.           System.out.println(HadoopExperimentUtil.displaySerializationExperimentResult(hadoopByteValue)); 
  33.            
  34.           IntWritable hadoopIntValue = new IntWritable(100); 
  35.           System.out.println(HadoopExperimentUtil.displaySerializationExperimentResult(hadoopIntValue) ); 
  36.            
  37.           FloatWritable hadoopFloatValue = new FloatWritable(73.54f); 
  38.           System.out.println(HadoopExperimentUtil.displaySerializationExperimentResult(hadoopFloatValue) ); 
  39.            
  40.           LongWritable hadoopLongValue = new LongWritable(82l); 
  41.           System.out.println(HadoopExperimentUtil.displaySerializationExperimentResult(hadoopLongValue) ); 
  42.            
  43.           DoubleWritable hadoopDoubleValue = new DoubleWritable(100.302d); 
  44.           System.out.println(HadoopExperimentUtil.displaySerializationExperimentResult(hadoopDoubleValue) ); 
  45.     } 
  46.  

 

最终控制台显示如下:

 
 
  1. 被测试的Hadoop类型为: org.apache.hadoop.io.BooleanWritable 
  2. 初始值为: false 
  3. 序列化后的字节数组长度为: 1 
  4. 序列化后的值为: 00 
  5.  
  6.  
  7.  
  8. 被测试的Hadoop类型为: org.apache.hadoop.io.ByteWritable 
  9. 初始值为: 3 
  10. 序列化后的字节数组长度为: 1 
  11. 序列化后的值为: 03 
  12.  
  13.  
  14.  
  15. 被测试的Hadoop类型为: org.apache.hadoop.io.IntWritable 
  16. 初始值为: 100 
  17. 序列化后的字节数组长度为: 4 
  18. 序列化后的值为: 00000064 
  19.  
  20.  
  21.  
  22. 被测试的Hadoop类型为: org.apache.hadoop.io.FloatWritable 
  23. 初始值为: 73.54 
  24. 序列化后的字节数组长度为: 4 
  25. 序列化后的值为: 4293147b 
  26.  
  27.  
  28.  
  29. 被测试的Hadoop类型为: org.apache.hadoop.io.LongWritable 
  30. 初始值为: 82 
  31. 序列化后的字节数组长度为: 8 
  32. 序列化后的值为: 0000000000000052 
  33.  
  34.  
  35.  
  36. 被测试的Hadoop类型为: org.apache.hadoop.io.DoubleWritable 
  37. 初始值为: 100.302 
  38. 序列化后的字节数组长度为: 8 
  39. 序列化后的值为: 40591353f7ced917 

 

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





本文转自 charles_wang888 51CTO博客,原文链接:http://blog.51cto.com/supercharles888/885400,如需转载请自行联系原作者

目录
相关文章
|
23天前
|
分布式计算 资源调度 Hadoop
Hadoop-10-HDFS集群 Java实现MapReduce WordCount计算 Hadoop序列化 编写Mapper和Reducer和Driver 附带POM 详细代码 图文等内容
Hadoop-10-HDFS集群 Java实现MapReduce WordCount计算 Hadoop序列化 编写Mapper和Reducer和Driver 附带POM 详细代码 图文等内容
76 3
|
3月前
|
机器学习/深度学习 存储 分布式计算
Hadoop与机器学习的融合:案例研究
【8月更文第28天】随着大数据技术的发展,Hadoop已经成为处理大规模数据集的重要工具。同时,机器学习作为一种数据分析方法,在各个领域都有着广泛的应用。本文将介绍如何利用Hadoop处理大规模数据集,并结合机器学习算法来挖掘有价值的信息。我们将通过一个具体的案例研究——基于用户行为数据预测用户留存率——来展开讨论。
174 0
|
5月前
|
存储 分布式计算 算法
|
6月前
|
SQL 分布式计算 Hadoop
[AIGC ~大数据] 深入理解Hadoop、HDFS、Hive和Spark:Java大师的大数据研究之旅
[AIGC ~大数据] 深入理解Hadoop、HDFS、Hive和Spark:Java大师的大数据研究之旅
172 0
|
分布式计算 资源调度 Hadoop
Hadoop基础学习---5、MapReduce概述和WordCount实操(本地运行和集群运行)、Hadoop序列化
Hadoop基础学习---5、MapReduce概述和WordCount实操(本地运行和集群运行)、Hadoop序列化
|
存储 分布式计算 搜索推荐
基于hadoop的短视频用户画像研究_kaic
摘 要 在这个互联网迅速发展的时代,网络和信息技术都跟上了时代的潮流,在互联网中的用户数据也出现了爆炸性的增长。用户的各种日常行为都通过互联网被记录下来,对于所有的互联网企业来说,想要从激烈的竞争中脱颖而出,就需要企业以用户为中心,通过这些庞大的用户行为数据了解用户的真实意图。用户画像是对用户数据化、信息化和标签化的描述,企业可以通过用户画像抽象出用户的商业全貌,从而对每个用户群体进行精细化、个性化的营销。但同时,很多企业都有多个业务系统,而且各个业务系统之间由于信息不全,无法构建统一清晰的用户画像。 基于以上背景,论文设计一个整合多种业务数据源,建立企业体系化用户标签的高灵活性、高扩展性
|
JSON Dart 安全
【Flutter框架】项目的手动序列化小项目以及对于进程异步性和格式化代码的研究
【Flutter框架】项目的手动序列化小项目以及对于进程异步性和格式化代码的研究
|
存储 分布式计算 自然语言处理
Hadoop序列化、概述、自定义bean对象实现序列化接口(Writable)、序列化案例实操、编写流量统计的Bean对象、编写Mapper类、编写Reducer类、编写Driver驱动类
Hadoop序列化、概述、自定义bean对象实现序列化接口(Writable)、序列化案例实操、编写流量统计的Bean对象、编写Mapper类、编写Reducer类、编写Driver驱动类
Hadoop序列化、概述、自定义bean对象实现序列化接口(Writable)、序列化案例实操、编写流量统计的Bean对象、编写Mapper类、编写Reducer类、编写Driver驱动类
|
分布式计算 资源调度 Java
Hadoop中的MapReduce概述、优缺点、核心思想、编程规范、进程、官方WordCount源码、提交到集群测试、常用数据序列化类型、WordCount案例实操
Hadoop中的MapReduce概述、优缺点、核心思想、编程规范、进程、官方WordCount源码、提交到集群测试、常用数据序列化类型、WordCount案例实操
Hadoop中的MapReduce概述、优缺点、核心思想、编程规范、进程、官方WordCount源码、提交到集群测试、常用数据序列化类型、WordCount案例实操
|
存储 分布式计算 自然语言处理

相关实验场景

更多