3.18 序列化
3.18.1 概念
序列化:将结构化对象转化为字节流以便在网络上传输或写入磁盘持久存储的过程
反序列化:将字节流转回结构化对象的逆过程
Java 的序列化 (Serializable) 是一个重量级序列化框架, 一个对象被序列化后, 会附带很多额外的信息 (各种校验信息, header, 继承体系等), 不便于在网络中高效传输. 因此 Hadoop 自己开发了一套序列化机制(Writable), 精简高效. 不用像 Java 对象类一样传输多层的父子关系, 需要哪个属性就传输哪个属性值, 大大的减少网络传输的开销
3.18.2 应用领域
进程间通信
永久存储
3.18.3 特点
紧凑:充分利用网络带宽资源和存储空间
快速:减少序列化和反序列化的性能开销
可扩展:兼容老格式的消息
互操作:支持不同的语言
3.18.4 实现
Java 自己的序列化机制:java.io.Serializable
Hadoop自己的序列化机制:org.apache.hadoop.io.Writable
3.18.5 常用接口
org.apache.hadoop.io. Writable
序列化的对象需实现的一个接口
Hadoop 的 MapReduce 框架中 key 或 value 均需实现这个接口
该接口包含两个抽象方法:
org.apache.hadoop.io. WritableComparable
继承自上述 Writable 接口和 java.lang.Comparable 接口
Hadoop 的 MapReduce 框架中的 key 必须实现这个接口
org.apache.hadoop.io. RawComparator
继承自 java.util.Comparator
一个抽象方法:可在数据流中比较对象
3.18.6 层次结构
3.18.7 Java 类型
Writable 类对 Java 基本数据类型提供了封装
short 和 char除外,可以使用 IntWritable 存储
所有的封装包含 get() 和 set() 两方法用于读取或设置封装的值
Java基本类型 | Writable实现 | 序列化大小(字节) |
---|---|---|
boolean | BooleanWritable | 1 |
byte | ByteWritable | 1 |
short | ShortWritable | 2 |
int | IntWritable | 4 |
VintWritable | 1~5 | |
float | FloatWritable | 4 |
long | LongWritable | 8 |
VlongWritable | 1~9 | |
double | DoubleWritable | 8 |
3.18.8 Writable 定制package com.briup.Bean;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.io.Writable;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
public class YearAndStation implements Writable {
private long year;
private String station;
public YearAndStation() {
}
public YearAndStation(long year, String station) {
this.year = year;
this.station = station;
}
public long getYear() {
return year;
}
public void setYear(long year) {
this.year = year;
}
public String getStation() {
return station;
}
public void setStation(String station) {
this.station = station;
}
@Override
public String toString() {
return "YearAndStation{" +
"year=" + year +
", station=" + station +
'}';
}
/**
*序列化
*/
public void write(DataOutput out) throws IOException {
out.writeLong(year);
out.writeUTF(station);
}
/**
* 反序列化
*/
public void readFields(DataInput in) throws IOException {
this.year=in.readLong();
this.station=in.readUTF();
}
}
注意:
序列化对象作为Mapper输出的键基于WritableComparable定制,换言之,定制的序列化对象需要比较规则或排序规则基于WritableComparable实现,否则可以使用Writable实现
序列化和反序列化中写和读取数据的顺序必须保持一致