Hadoop - 序列化机制详解(附:与Java原生序列化对比样例)
作者:hangge | 2024-07-05 08:32
1,什么是序列化和反序列化?
(1)序列化就是把内存中的对象,转换成字节序列(或其他数据传输协议)以便于存储到磁盘(持久化)和网络传输。
(2)反序列化就是将收到字节序列(或其他数据传输协议)或者是磁盘的持久化数据,转换成内存中的对象。
2,序列化机制在 Hadoop 中的作用
(1)数据传输:在 Hadoop 的分布式架构中,数据需要在不同节点之间传输。序列化将数据对象转化为字节流,使得这些数据可以通过网络进行传输。
- 例如,在 MapReduce 框架中,map 任务产生的中间数据需要传输到 reduce 任务所在的节点,这就需要通过序列化来实现。
(2)数据存储:Hadoop 的分布式文件系统 HDFS(Hadoop Distributed File System)存储的数据也是通过序列化的方式进行持久化的。序列化后的数据更为紧凑,节省存储空间,并且能够快速进行读写操作。
- 例如,SequenceFile 格式就是 Hadoop 中常用的一种二进制文件格式,通过序列化存储键值对数据。
3,为什么不用 Java 的序列化
Java 的序列化是一个重量级序列化框架(Serializable),一个对象被序列化后,会附带很多额外的信息(各种校验信息,Header,继承体系等),不便于在网络中高效传输。所以,Hadoop 自己开发了一套序列化机制(Writable)。
4,Hadoop 序列化优势
(1)紧凑:Hadoop 中最稀缺的资源是宽带,所以紧凑的序列化机制可以充分的利用宽带。
(2)快速:通信时大量使用序列化机制,因此,需要减少序列化和反序列化的开销。
(3)可扩展:随着通信协议的升级而可升级。
(4)互操作:支持不同开发语言的通信。
5,Hadoop 提供的序列化类
下面是 Hadoop 中提供的常用的基本数据类型的序列化类:
Java 基本类型 | Writable | 序列化大小(字节) |
布尔型(boolean) | BooleanWritable | 1 |
字节型(byte) | ByteWritable | 1 |
整型(int) | IntWritable | 4 |
VIntWritable | 1~5 | |
浮点型(float) | FloatWritable | 4 |
长整型(long) | LongWritable | 8 |
VLongWritable | 1~9 | |
双精度浮点型(double) | DoubleWritable | 8 |
附:Java 序列化机制与 Hadoop 序列化机制对比样例
(1)下面是一个 Java 的序列化代码,它将一个 Student 对象序列化后写入到本地文件中:
(2)下面是使用 Hadoop 序列化机制将 Student 对象序列化后写入到本地文件中:
import java.io.FileOutputStream; import java.io.ObjectOutputStream; import java.io.Serializable; /** * Java中的序列化机制 */ public class JavaSerialize { public static void main(String[] args)throws Exception { //创建Student对象,并设置id和name属性 StudentJava studentJava = new StudentJava(); studentJava.setId(1L); studentJava.setName("hangge"); //将Student对象的当前状态写入本地文件中 FileOutputStream fos = new FileOutputStream("/Volumes/BOOTCAMP/test/student_java.txt"); ObjectOutputStream oos = new ObjectOutputStream(fos); oos.writeObject(studentJava); oos.close(); fos.close(); } } class StudentJava implements Serializable{ private static final long serialVersionUID=1L; private Long id; private String name; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
(2)下面是使用 Hadoop 序列化机制将 Student 对象序列化后写入到本地文件中:
import org.apache.hadoop.io.Writable; import java.io.*; /** * Hadoop中的序列化机制 */ public class HadoopSerialize { public static void main(String[] args) throws Exception{ //创建Student对象,并设置id和name属性 StudentWritable studentWritable = new StudentWritable(); studentWritable.setId(1L); studentWritable.setName("hangge"); //将Student对象的当前状态写入本地文件中 FileOutputStream fos = new FileOutputStream("/Volumes/BOOTCAMP/test/student_hadoop.txt"); ObjectOutputStream oos = new ObjectOutputStream(fos); studentWritable.write(oos); oos.close(); fos.close(); } } class StudentWritable implements Writable { private Long id; private String name; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public void write(DataOutput out) throws IOException { out.writeLong(this.id); out.writeUTF(this.name); } @Override public void readFields(DataInput in) throws IOException { this.id = in.readLong(); this.name = in.readUTF(); } }
(3)对比生成的两个文件的大小,可以发现 Java 序列化的文件大小将近是 Hadoop 序列化文件大小的 10 倍左右。
全部评论(0)