Hadoop序列化
序列化:就是把内存中的对象转换成字节序列(或其他数据传输协议),以便于存储到磁盘(持久化)和网络传输。
反序列化:就是将收到的字节序列(或其他数据传输协议)或者是磁盘的持久化数据,转换成内存中的对象。
因为Java自带的序列化存储了很多额外信息(各种校验、Header、继承体系等),是一个重量级序列化框架,不便于在网络中传输,所以Hadoop有自己的一套序列化。
Hadoop序列化的特点:
- 紧凑:存储空间少
- 快速:传输速度快
- 互操作性:支持多语言的交互
实际开发中,Hadoop自带的Text、IntWritable等基本的序列化类型往往不够用,需要自定义一些可序列化的 JavaBean。
自定义需要序列化的类:
- 必须实现
Writable接口 - 反序列化时,需要反射调用空参构造函数,所以必须要有空参构造
- 实现序列化方法
write(): - 实现反序列化方法
readFields(): - 注意反序列化顺序要和序列化的顺序完全一致(先进先出)
- 如果想把结果显示在文件中,还需要重写
toString()方法 - 如果要把自定义的类的对象放在key中传输,则还需要实现
Comparable接口,因为MapReduce框架中的Shuffle过程要求key必须能够排序
示例:
package com.study.mapreduce.writable;import org.apache.hadoop.io.Writable;import java.io.DataInput;import java.io.DataOutput;import java.io.IOException;public class MyWritable implements Writable,Comparable<MyWritable> {private Integer id;private Long scale;private Integer age;/*** 需要有无参构造器*/public MyWritable() {}/*** 序列化* @param out* @throws IOException*/@Overridepublic void write(DataOutput out) throws IOException {out.writeInt(id);out.writeLong(scale);out.writeInt(age);}/*** 反序列化* @param in* @throws IOException*/@Overridepublic void readFields(DataInput in) throws IOException {// 读取顺序要和write方法写的顺序一致,即先进先出id = in.readInt();scale = in.readLong();age = in.readInt();}/*** 如果想当做key在MapReduce中传输,需要实现Comparable,因为Shuffle过程要求key必须能排序* @param o* @return*/@Overridepublic int compareTo(MyWritable o) {return this.id > o.getId() ? -1 : 1;}/*** 为方便查看,还可以重写toString()方法* @return*/@Overridepublic String toString() {MessageFormat mf = new MessageFormat("MyWritable:{id:[0], scale:[1], age:[2]}");return mf.format(new Object[]{id, scale, age});}// 生成getter/setterpublic Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public Long getScale() {return scale;}public void setScale(Long scale) {this.scale = scale;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}}
