1)什么是序列化
将结构化对象转换成字节流以便于进行网络传输或写入持久存储的过程。
2)什么是反序列化
将字节流转化为一系列结构化对象的过程。
序列化的用途
1)作为一种持久化格式
2)作为一种通信的数据格式
3)作为一种数据拷贝、克隆机制
序列化的特征:
1)紧凑:Hadoop中最稀缺的资源是宽带,所以紧凑的序列化机制可以充分的利用宽带。
2)快速:通信时大量使用序列化机制,因此,需要减少序列化和反序列化的开销。
3)可扩展:随着通信协议的升级而可升级。
4)互操作:支持不同开发语言的通信。
hadoop 1.x 序列化仅满足了紧凑和快速的特点。
Java序列化和反序列化
1)创建一个对象实现了Serializable
2)序列化:ObjectOutputStream.writeObject(序列化对象)
反序列化:ObjectInputStream.readObject()返回序列化对象
Hadoop序列化
Hadoop的序列化不采用Java的序列化,而是实现了自己的序列化机制。
Hadoop通过Writable接口实现的序列化机制,不过没有提供比较功能,所以和Java中的Comparable接口合并,提供了一个接口WritableComparable。
Writable接口提供了两个方法,Write和readFiles
外部集合的比较器
Comparable是用于集合内部的数据比较,在java.lang包中,Comparator是用于集合外部的数据比较,在java.util包中。
Hadoop序列化类
实现了WritableComparable接口的类
基础类:BooleanWritable,ByteWritable,IntWritable,VIntWritable,
FIntWritable,LongWritbale,VLongWritavle,DoubleWritable
高级类:NullWritable,Text,BytesWritable,MDSHash,ObjectWritable,
GenericWritable
仅实现了Writable接口的类:
数组:AbstractWritable,TwoDArrayWritable
映射:AbstractMapWritable,MapWritable,SortedMapWritable
序列化框架
apache avro
1.丰富的数据结构类型
2.快速可压缩的二进制数据形式
3.存储持久数据的文件容器
4.远程过程调用RPC
5.简单的动态语言结合功能,Avro和动态语言结合后,读写文件和使用RPC协议都不需要生成代码,而代码生成作为一种可选的优化只值得在静态类型语言中实现。
Facebook Thrift
1.是一种可伸缩的跨语言服务的发展软件框架。
2.它结合了功能强大的软件堆栈的代码生成引擎,以建设服务,工作效率和无缝地与C++,C#,Java,Python和PHP和Ruby结合。
3.允许定义一个简单的定义文件中的数据类型和服务接口,以作为输入文件,编译器生成代码用来方便地生成RPC客户端和服务器通信的无缝跨编程语言。
Google Protocolbuffer
PB是Google开源的一种轻量级的结构化数据存储格式,可以用于结构数据的序列化和反序列化,很适合做数据存储或RPC数据交换格式
PB优点
1)和XML相比,更小、更快、也更简单。只需使用protobuf对数据结构进行一次描述,即可利用各种不同语言或从各种不同数据流中对数据化结构进行读写。
2)“向后”兼容性好,不必破坏已部署的、依靠老数据格式的程序就可以对数据结构进行升级。
3)语义清晰,无需类似XML解析器的东西(因为Protobuf编译器会将.proto文件编译生成对应的数据访问类以对Protobuf数据进行序列化、反序列化操作)。
PB的缺点
1)Protobuf与XML相比也有不足之处。它功能简单,无法用来表示复杂的概念。
2)由于文本并不适合用来描述数据结构,所以Protobuf也不适合用来对基于文本的标记文档(如HTML)建模。另外,由于XML具有某种程度上的自解释性,它可以被人直接读取编辑,在这一点上Protobuf不行,它以二进制的方式存储,除非你有.proto定义,否则你没法直接读出Protobuf的任何内容
import java.io.DataInput;
import java.io.DataInputStream;
import java.io.DataOutput;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.io.WritableComparable;
public class TestWritableComparable {
public static void main(String[] agrs) throws Exception{
Student s = new Student("li",20,"man");
FileOutputStream fout = new FileOutputStream(
new File("/usr/local/test.txt"));
DataOutputStream out = new DataOutputStream(fout);
s.write(out);
fout.close();
out.close();
Student s1 = new Student();
FileInputStream fin = new FileInputStream(
new File("/usr/local/test.txt"));
DataInputStream in = new DataInputStream(fin);
s1.readFields(in);
System.out.println(s1.toString());
}
}
class Student implements WritableComparable<Student>{
private Text name = new Text();
private IntWritable age = new IntWritable();
private Text sex = new Text();
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + ", sex=" + sex + "]";
}
public Student() {
super();
}
public Student(String name, int age, String sex) {
super();
this.name = new Text(name);
this.age = new IntWritable(age);
this.sex = new Text(sex);
}
public Text getName() {
return name;
}
public void setName(Text name) {
this.name = name;
}
public IntWritable getAge() {
return age;
}
public void setAge(IntWritable age) {
this.age = age;
}
public Text getSex() {
return sex;
}
public void setSex(Text sex) {
this.sex = sex;
}
@Override
public void readFields(DataInput in) throws IOException {
name.readFields(in);
age.readFields(in);
sex.readFields(in);
}
@Override
public void write(DataOutput out) throws IOException {
name.write(out);
age.write(out);
sex.write(out);
}
@Override
public int compareTo(Student o) {
int result = 0;
if((result = name.compareTo(o.getName())) != 0){
return result;
}
if((result = age.compareTo(o.getAge())) != 0){
return result;
}
if((result = sex.compareTo(o.getSex())) != 0){
return result;
}
return result;
}
}