1 序列化的概念
1、什么是序列化?
将结构化对象转换成字节流以便于进行网络传输或写入持久存储的过程。
2、什么是反序列化?
将字节流转换为一系列结构化对象的过程。
2 序列化用途:
1、作为一种持久化格式。
2、作为一种通信的数据格式。
3、作为一种数据拷贝、克隆机制。
3 Java序列化和反序列化
1、创建一个对象并实现Serializable
2、序列化:ObjectOutputStream.writeObject(序列化对象)
反序列化:ObjectInputStream.readObject()返回序列化对象
4 Hadoop序列化机制
Hadoop的序列化机制与java的序列化机制不同,它将对象序列化到流中,值得一提的是java的序列化机制是不断的创建对象,但在Hadoop的序列化机制中,用户可以复用对象,这样就减少了java对象的分配和回收,提高了应用效率。- 排列紧凑:尽量减少带宽,加快数据交换速度
- 处理快速:进程间通信需要大量的数据交互,使用大量的序列化机制,必须减少序列化和反序列的开支
- 跨语言:可以支持不同语言间的数据交互啊,如C++
- 可扩展:当系统协议升级,类定义发生变化,序列化机制需要支持这些升级和变化
Writable
接口提供两个方法(write和readFields)。
package org.apache.hadoop.io;
public interface Writable {
void write(DataOutput out) throws IOException;
void readFields(DataInput in) throws IOException;
需要进行比较的话,要实现WritableComparable接口。
public interface WritableComparable<T> extends Writable, Comparable<T>{
}
- 比如mapreduce中需要对key值进行相应的排序。
Writable接口
Text
Text是UTF-8的Writable,可以理解为java.lang.String相类似的Writable。Text类替代了UTF-8类。Text是可变的,其值可以通过调用set()方法改变。最大可以存储2GB的大小。
NullWritable
NullWritable是一种特殊的Writable类型,它的序列化长度为零,可以用作占位符。
BytesWritable
BytesWritable是一个二进制数据数组封装,序列化格式是一个int字段。
例如:一个长度为2,值为3和5的字节数组序列后的结果是:
@Test
public void testByteWritableSerilizedFromat() throws IOException {
BytesWritable bytesWritable=new BytesWritable(new byte[]{3,5});
byte[] bytes=SerializeUtils.serialize(bytesWritable);
Assert.assertEquals(StringUtils.byteToHexString(bytes),"000000020305"); //true
}
BytesWritable是可变的,其值可以通过调用set()方法来改变。
ObjectWritable
ObjectWritable适用于字段使用多种类型时。
Writable集合
1、ArrayWritable
和TwoDArrayWritable
是针对数组和二维数组。
2、MapWritable
和SortedMapWritable
是针对Map和SortMap。
自定义Writable
1、实现Writable Comparable接口
2、实现相应的接口方法:
A.write() //将对象转换为字节流并写入到输出流out中。
B.readFileds() //从输入流in中读取字节流并发序列化为对象。
C.compareTo(o) //将this对象和对象o进行比较。
5 Hadoop序列化优势:
1、紧凑:Hadoop中最稀缺的资源是宽带,所以紧凑的序列化机制可以充分的利用宽带。
2、快速:通信时大量使用序列化机制,因此,需要减少序列化和反序列化的开销。
3、可扩展:随着通信协议的升级而可升级。
4、互操作:支持不同开发语言的通信。
Hadoop1.x 序列化仅满足了紧凑和快速的特点。
Hadoop序列化的作用
序列化在分布式环境的两大作用:进程间通信,永久存储。
Hadoop节点间通信。
序列化框架
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数据交换格式。
优点:
与 XML相比,它更小、更快、也更简单。你可以定义自己的数据结构,然后使用代码生成器生成的代码来读写这个数据结构。你甚至可以在无需重新部署程序的情况下更新数据结构。只需使用 Protobuf 对数据结构进行一次描述,即可利用各种不同语言或从各种不同数据流中对你的结构化数据轻松读写。
它有一个非常棒的特性,即“向后”兼容性好,人们不必破坏已部署的、依靠”老”数据格式的程序就可以对数据结构进行升级。这样您的程序就可以不必担心因为消息结构的改变而造成的大规模的代码重构或者迁移的问题。因为添加新的消息中的 field 并不会引起已经发布的程序的任何改变。
Protocolbuffer语义更清晰,无需类似 XML 解析器的东西(因为 Protobuf 编译器会将 .proto 文件编译生成对应的数据访问类以对 Protobuf 数据进行序列化、反序列化操作)。使用 Protobuf 无需学习复杂的文档对象模型,Protobuf 的编程模式比较友好,简单易学,同时它拥有良好的文档和示例,对于喜欢简单事物的人们而言,Protobuf 比其他的技术更加有吸引力。
不足:
Protbuf 与 XML 相比也有不足之处。它功能简单,无法用来表示复杂的概念。
由于文本并不适合用来描述数据结构,所以 Protobuf 也不适合用来对基于文本的标记文档(如 HTML)建模。另外,由于 XML 具有某种程度上的自解释性,它可以被人直接读取编辑,在这一点上 Protobuf 不行,它以二进制的方式存储,除非你有 .proto 定义,否则你没法直接读出 Protobuf 的任何内容。
Hadoop2.X用到的Protocolbuffer