1、序列化:将内存中的对象,转成字节序列,可以用于在网络传输或者持久化到磁盘上。
2、反序列化:将网络中接收到的字节序列或者磁盘持久化的数据,转换成内存中的对象。
3、Hadoop本身是Java开发,为什么不直接使用java序列化框架(Serializable)?
Java的序列化是一个重量级框架,一个对象被序列化之后,除了序列化数据之外,还会附带很多信息(数据校验信息,Header等),无效的数据太多,在网络传输较慢,序列化后很占内存。所以,Hadoop自己实现一套序列化机制(Writable)。
4、Hadoop 序列化特点:
4.1、紧凑:带宽是集群中信息传递的最宝贵的资源,所以我们必须设法缩小传递信息的大小。
java序列化不够灵活,为了更好的控制序列化的整个流程所以使用Writable。
java序列化会保存类的所有信息 依赖等,hadoop序列化不需要。
4.2、对象可重用:JDK的反序列化会不断地创建对象,会造成一定的系统开销,但是在hadoop的反序列化中,能重复的利用一个对象的readField方法来重新产生不同的对象。
java序列化每次序列化都要重新创建对象,内存消耗大。Writable可以重用。
5、自定义Bean对象实现序列化接口(Writable)
(1)、必须实现Writable接口;
(2)、必须有空参构造方法,反序列化时,创建对象,需要反射调用空参构造。
(3)、重写序列化方法(write);
(4)、重写反序列化方法(readFields);
(5)、反序列化的顺序要跟序列化的顺序完全一致;
(6)、重写toString方法,方便后面使用;
(7)、bean对象在作为key传输时,需要实现Comparable接口,因为对象在shuffle过程中,需要对key会进行排序。
6、序列化demo:
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import org.apache.hadoop.io.Writable;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
@Data
@NoArgsConstructor
@Accessors(chain = true)
public class Student implements Writable,Comparable<Student> {
private String name; //姓名
private char sex; //性别
private int age; //年龄
private double salary; //薪资
//序列化
@Override
public void write(DataOutput out) throws IOException {
out.writeUTF(name);
out.writeChar(sex);
out.writeInt(age);
out.writeDouble(salary);
}
//反序列化
@Override
public void readFields(DataInput in) throws IOException {
name = in.readUTF();
sex = in.readChar();
age = in.readInt();
salary = in.readDouble();
}
@Override
public int compareTo(Student stu) { //根据薪资比较
return this.salary > stu.getSalary() ? -1 : 1;
}
}