Hadoop Writable和java.io.serialization之间有什么联系和区别?
要实现Writable
接口,可以在Hadoop中序列化对象。 那么Hadoop Writable
和java.io.serialization
之间的联系和区别是什么?
底层存储差异:
Java Serializable
Serializable不假设存储值的类是已知的,并且标记具有其类的实例,即。 它写入有关对象的元数据,包括类名,字段名和类型,以及它的超类。 ObjectOutputStream和ObjectInputStream稍微优化了这一点,因此在第一个类之后为类的实例编写了5个字节的句柄。 但是随后无法随机访问带句柄的对象序列,因为它们依赖于流状态。 这使排序变得复杂。
Hadoop可写
在定义“可写”时,您知道预期的类。 因此,在反序列化时,Writable不会将它们的类型存储在序列化表示中,您知道预期的内容。 例如。 如果输入键是LongWritable,则要求空的LongWritable实例从输入数据流填充自身。 由于不需要存储元信息(类名,字段,类型,超类),因此可以生成更紧凑的二进制文件,直接的随机访问和更高的性能。
一些好的读物:
对于Java Serializable:
- http://docs.oracle.com/javase/7/docs/platform/serialization/spec/serial-arch.html
- http://www.javaworld.com/javaworld/jw-02-2006/jw-0227-control.html
Hadoop可写
用Doug Cutting的话来说:
Writable接口与Serializable略有不同。 Serializable不假定存储值类是已知的。 所以每个实例都用它的类标记。 ObjectOutputStream和ObjectInputStream稍微优化了这一点,因此在第一个类之后为类的实例编写了5个字节的句柄。 但是随后无法随机访问带句柄的对象序列,因为它们依赖于流状态。 这使排序变得复杂。
另一方面,可写入假定应用程序知道预期的类。 应用程序必须能够创建一个实例才能调用readFields()。 所以这个类不需要与每个实例一起存储。 这导致更加紧凑的二进制文件,直接的随机访问和通常更高的性能。
可以说Hadoop可以使用Serializable。 对于序列化对性能至关重要的每个类,可以覆盖writeObject或writeExternal。 (MapReduce是非常i / o密集型的,因此几乎每个类的序列化都是性能关键。)可以实现ObjectOutputStream.writeObjectOverride()和ObjectInputStream.readObjectOverride()以使用更紧凑的表示,例如,不需要标记每个具有类的文件中的顶级实例。 这可能需要至少与Haddop在Writable,ObjectWritable等中的代码一样多,并且代码会更复杂一些,因为它会尝试解决不同的打字模型。 但它可能具有更好的内置版本控制的优势。 或者是吗?
Serializable的版本机制是让类定义一个名为serialVersionUID的静态。 这允许人们防止不兼容的更改,但不容易允许实现后向兼容性。 为此,应用程序必须明确处理版本。 它必须以特定于类的方式推断在阅读时编写的版本,以决定要做什么。 但Serializeable的版本机制不支持这个或多于或少于Writable。
你必须经历一次这个主题 。
- 如何使用Java有效地读取Hadoop(HDFS)文件中的第一行?
- 无法在hadoop 2.4.0上运行MapReduce作业
- 错误:java.lang.IllegalArgumentException:即使使用变通方法,比较方法也违反了其一般合同
- 为什么检查hadoop中是否存在文件会导致NullPointerException?
- mapreduce组合键样本 – 不显示所需的输出
- 如何生成海量数据?
- hadoop java.net.URISyntaxException:绝对URI中的相对路径:rsrc:hbase-common-0.98.1-hadoop2.jar
- 如何在HBase中实现分页?
- 使用hadoop和java命令执行map-reduce作业之间有什么区别