要实现Writable
接口,可以在 Hadoop 中序列化对象。那么 HadoopWritable
和Hadoop 之间的联系和区别是java.io.serialization
什么?
2 回答
潜在的存储差异:
Java 可序列化
Serializable 不假设存储值的类是已知的,并且使用其类标记实例。它写入关于对象的元数据,其中包括类名、字段名和类型,以及它的超类。ObjectOutputStream 和 ObjectInputStream 对此进行了一些优化,以便在第一个之后为类的实例编写 5 字节句柄。但是带有句柄的对象序列不能被随机访问,因为它们依赖于流状态。这使排序等事情变得复杂。
Hadoop可写
在定义“可写”时,您知道预期的类。因此,Writables 不会将其类型存储在序列化表示中,因为在反序列化时,您知道预期的内容。例如。如果输入键是 LongWritable,则要求空的 LongWritable 实例从输入数据流中填充自身。由于不需要存储元信息(类名、字段、它们的类型、超类),这会导致二进制文件更加紧凑、直接随机访问和更高的性能。
一些不错的读物:
对于 Java 可序列化:
- 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 更多或更少。
你必须通过这个线程一次。