整套大数据学习资料(视频+笔记)百度网盘无门槛下载:http://www.edu360.cn/news/content?id=3377

4.3 序列化框架

hadoop 花牛 10℃ 0评论

尽管大多数MapReduce程序使用的都是Writable类型的键和值,但这并不是MapReduce API强制使用的。事实上,可以使用任何类型,只要能有一种机制对每个类型进行类型与二进制表示的来回转换。

为了支持这一机制,Hadoop有一个针对可替换序列化框架(serialization framework)的API。序列化框架用一个Serialization实现(包含在org.apache.hadoop.io.serializer包)来表示。例如,WritableSerialization类是对Writable类型的Serialization实现。

Serialization对象定义了从类型到serializer实例(将对象转换为字节流)和Deserializer实例(将字节流转换为对象)的映射方式。

io.serizalizations属性设置为一个由逗号分隔的类名列表,即可注册Serialization实现。它的默认值包括org.apache.hadoopio.serializer.WritableSerialization 和 Avro 指定序列化和自反序列化类,这意味着只有Writable对象和Avro对象才可以在外部序列化和反序列化。

Hadoop 包含一个名为 JavaSerialization 的类,该类使用 Java Object Serialization。尽管它方便了我们在MapReduce程序中使用标准的Java类型,如IntegerString,但不如Writable高效,所以不建议使用(参见以下内容)。

为什么不用 Java Object Serialization?

Java有自己的序列化机制,称为“Java Object Serialization”(通常简称 为“Java Serialization”),该机制与编程语言紧密相关,所以我们很自然会问为什么不在Hadoop中使用该机制针对这个问题,Doug Cutting 是这样解释的:

“为什么开始设计Hadoop的时候我不用Java Serialization?因为它看起来太复杂,而我认为需要有一个至精至简的机制,可以用于精确控制对象的读和写,这个机制将是Hadoop的核心。你用Java Serialization虽然可以获得一些控制权,但用起来非常纠结。

不用RMI也出于类似的考虑高效、高性能的进程间通信是Hadoop的关键。我觉得我们需要精确控制连接、延迟和缓冲的处理方式,RMI对此无能为力。”

问题在于Java Serialization不满足先前列出的序列化格式标准:精简、 快速、可扩展、支持互操作

Java Serialization 并不精简。实例化 java.io.Serializable 或者java.io.Externalizable的类需要将其类名和对象表示写入序列化后的数据流中。同一个类后续的实例只引用第一次出现的句柄,这占5个字节。引用句柄不太适用于随机访问,因为被引用的类可能出现在先前数据流的任何位置,也就是说,需要在数据流中存储状态。更糟糕的是句柄引用会对序列化数据流中的排序记录造成巨大的破坏,因为一个特定类的第一个记录是不同的,必须当作特殊情况区别对待。

不把类名写到数据流可以避免所有这些问题,Writable接口采取的正是这种做法。这需要假设客户端知道会收到什么类型。其结果是,这个格式比Java Serialization更精简,同时又支持随机存取和排序,因为流中的每一条记录均独立于其他记录(所以数据流是无状态的)。

Java Serialization是序列化图对象的通用机制,所以它有序列化和反序列化开销。更有甚者,它有一些从数据流中反序列化对象时,反序列化程序需要为每个对象新建一个实例。另一方面,Writable对象可以(并且通常)重用。例如,对于MapReduce作业(主要对只有几个类型的几十亿个对象进行序列化和反序列化),不需要为新建对象分配空间而得到的存储节省是非常可观的。

至于可扩展性,Java Serialization支持演化类型,但是难以使用。(不支持Writable类型,得靠程序员自行搞定。)

从原则上讲,其他编程语言能够理解Java Serialization流协议(由Java ObjectSerialization定义),但事实上,其他语言的实现并不多,所以只有Java实现。对此,Writable的情况也不例外。

序列化IDL

还有许多其他序列化框架从不同的角度来解决该问题:不通过代码来定义类型,而是使用“接口定义语言”(Interface Description Language,IDL)以不依赖于具体语言的方式进行声明。由此,系统能够为其他语言生成类型,这种形式能有效提髙互操作能力。它们一般还会定义版本控制方案(使类型的演化直观易懂)。

Hadoop 自己的 Record I/O(可以在 org.apache.hadoop.record 包中找到)有一个IDL(已编译到Writable对象中,有利于生成与MapReduce兼容的类型)。但是,不知何故,Record I/O并未得到广泛应用,而且Avro也不支持它。

Apache Thrift(http://thrift.apache.org/)和 Google 的 Protocol Buffers (https://developers.google.com/protocol-buffers/)是两个比较流行的序列化框架,但它们常用作二进制数据的永久存储格式。MapReduce格式对该类的支持有限,但在Hadoop内部,部分组件仍使用上述两个序列化框架来实现RPC和数据交换。

在下一小节,我们深入探讨Avro,这是一个基于IDL的序列化框架,非常适用于Hadoop的大规模数据处理。

转载请注明:全栈大数据 » 4.3 序列化框架

喜欢 (0)or分享 (0)
发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址