注:本文涉及书中4.3小结
序列化与反序列化
1. 定义
序列化(serialization):将结构化对象转化为字节流。
反序列化(deserialization):将字节流转回结构化对象的逆过程。
2. 应用场景
序列化在分布式数据处理的两大领域经常出现:进程间通信和永久存储。
在Hadoop中,多个节点上的进程间通信是通过RPC(远程过程调用)实现的。RPC协议将消息序列化成二进制流后发送到远程节点,远程节点再将二进制流反序列化为原始消息。
Hadoop使用序列化格式Wriable,这是Hadoop的核心。
补充
在Hadoop中,Mapper,Combiner,Reducer等阶段之间的通信都需要使用序列化与反序列化技术。举例来说,Mapper产生的中间结果(
序列化是Hadoop核心的一部分,在Hadoop中,位于org.apache.hadoop.io包中的Writable接口是Hadoop序列化格式的实现。
Writable接口
Writable接口定义了两个方法:
1. 状态写:将其状态写到DataOutput二进制流。
2. 状态读:DataOutput二进制流读取状态。
WritableComparable接口和comparator
补充
书中说的不太明白,故自己比较一下:Comparable接口 VS Comparator接口
在 “ 集合框架 ” 中有两种比较接口: Comparable 接口和 Comparator 接口。 Comparable 是通用的接口,用户可以实现它来完成自己特定的比较,而 Comparator 可以看成一种算法的实现,在需要容器集合实现比较功能的时候,来指定这个比较器,这可以看成一种设计模式,将算法和数据分 离。前者应该比较固定,和一个具体类相绑定;而后者比较灵活,它可以被用于各个需要比较功能的类使用。
一个类实现了 Camparable 接口表明这个类的对象之间是可以相互比较的。如果用数学语言描述的话就是这个类的对象组成的集合中存在一个全序。这样,这 个类对象组成的集合就可以使用 Sort 方法排序了。
而 Comparator 的作用有两个:
1 、如果类的设计师没有考虑到 Compare 的问题而没有实现 Comparable 接口,可以通过 Comparator 来实现比较算法进行排序;
2 、为了使用不同的排序标准做准备,比如:升序、降序或其他什么序。
Writable类
Hadoop自身提供了多种具体的Writable类,封装了常见的Java基本类型(boolean、byte、short、int、float、long和double等)和集合类型(BytesWritable、ArrayWritable和MapWritable等)。这些类型都位于org.apache.hadoop.io包中。
1. Java基本类型的Writable封装器
所有的封装包含get()和set()两种方法,用于读取和存储封装的值。
2. Text类型
Text是针对UTF-8序列的Writable类。
Text类型的索引、迭代、可变性、对String重新排序,详见书4.3.2小节。
书中还有:Text与String的比较
3. BytesWritable
BytesWritable是对二进制数据数组的封装。
它的序列化格式为:一个指定所含数据字节数的整数域(4字节,即8bit),后跟数据内容本身。
4. NullWritable
NullWritable是Writable的特殊类型,它的序列化长度为0,既不从数据流中读取数据,也不写入数据,充当占位符。
5. ObjectWritable和GenericWritable
ObjectWritable是对Java基本类型(String, enum, Writable, null或这些类型组成的数组)的一个通用封装。它在Hadoop RPC中用于对方法的参数和返回类型进行封装和解封装。当一个字段包含多种类型时,ObjectWritable非常有用。
Objectwritable 作为一个通用机制,这是相当浪费空间的,因为每次它被序列化肘,都要写入被封装类型的类名。GenericWritable 对此做出了改进,如果类型的数量不多并且事先可知,那么可以使用一个静态类型数组来提高效率,使用数组的索引来作为类型的序列化引用.这是GenericWritable 使用的方法,我们必须继承它以指定支持的类型。
6. Writable集合类
共有6个Writable集合类:
(1)+(2)ArrayWritable和TwoDArrayWritable
它们是对Writable的数组和二维数组的实现。常用函数包括toArray()、get()、set()
(3)ArrayPrimitiveWritable
对Java基本数组类型的一个封装。
(4)+(5)+(6)MapWritable,SortedMapWritable,EnumMapWritable
MapWritable:对集合和列表,枚举集合中的元素
SortedMapWritable:针对排序集合,枚举集合中的元素
EnumMapWritable:对集合的枚举类型采用EnumMapWritable
补充
AbstractMapWritable作为MapWritable抽象类并没有涉及到Map的键值对操作,而是从抽象层抽象出索引表,其实现类MapWritable和SortedMapWritable则是新增了Map变量,不同的之处在于SortedMapWritable是实现了排序了的TreeMap,自身已具有排序功能。
定制的Writable集合
书中范例4-7实现了存储一对Text对象的Writable
序列化框架
大部分的MapReduce程序都使用Writable键–值对作为输入和输出,但这并不是Hadoop强制使用的,其他序列化机制也能和Hadoop配合,并应用于MapReduce中。
目前,除了前面介绍过的Java序列化机制和Hadoop使用的Writable机制,还流行其他序列化框架,如Hadoop Avro、Apache Thrift和Google Protocol Buffer。
1. 序列化框架(Serialization)
MapReduce仅仅可以支持Writable做key,value吗?答案是否定的。事实上,可以使用任何类型:只要能有一种机制能对每个类型进行类型与二进制表示的来回转换。为此Hadoop提供了一个针对序列化做替换的框架来支持,他们在org.apache.hadoop.io.serializer包中,Writable可以作为MapReduce支持的类型也是因为实现了这个框架,类不多,我们从几个接口说起。
Hadoop提供了一个简单的序列化框架API,用于集成各种序列化实现,该框架由Serialization实现(在org.apache.hadoop.io.serializer包中)。
2. 序列化IDL
还有许多其他序列化框架从不同的角度来解决该问题:即不通过代码来定义类型,而是使用IDL(Interface Description Language, 接口定义语言)以不依赖于具体语言的方式进行声明。