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 倍左右。
全部评论(1)
写得好,航哥
站长回复:多谢你的夸奖