为什么一个可写的数据类型应该是可变的?

hs1ihplo  于 2021-06-03  发布在  Hadoop
关注(0)|答案(2)|浏览(397)

为什么可写数据类型应该是可变的?在map、combine、shuffle或reduce进程中使用text(vs string)作为key/value的数据类型有什么好处?
谢谢和问候,拉贾

iszxjhcz

iszxjhcz1#

简单地说,原因 Writable 不能是 ImmutablereadFields(DataInput) 中的方法 Writable . 就像 Hadoop 反序列化中的示例,以使用默认(无参数)构造函数和调用 readFields 解析值。因为在构造中没有赋值,所以对象必须是可变的。

elcex8rz

elcex8rz2#

您不能选择,这些数据类型必须是可变的。
原因是序列化机制。让我们看看代码:

// version 1.x MapRunner#run()
K1 key = input.createKey();
V1 value = input.createValue();

while (input.next(key, value)) {
   // map pair to output
   mapper.map(key, value, output, reporter);
   ...

所以我们重新使用同一个键/值对示例。为什么?我不知道当时的设计决策,但我认为这是为了减少垃圾对象的数量。请注意,hadoop非常古老,那时的垃圾收集器没有今天的效率高,但是即使在今天,如果您Map数十亿个对象并将它们作为垃圾直接丢弃,在运行时也会有很大的不同。
你为什么不能 Writable 真正不可变的类型是不能将字段声明为 final . 让我们用 IntWritable :

public class IntWritable implements WritableComparable {
  private int value;

  public IntWritable() {}

  public IntWritable(int value) { set(value); }
...

如果您使它不可变,它肯定不会再与序列化过程一起工作,因为您需要定义 value 最后。这是行不通的,因为键和值是在运行时通过反射示例化的。这需要一个默认构造函数,因此 InputFormat 无法猜测填充最终数据字段所需的参数。因此,重用示例的整个概念显然与不变性的概念相矛盾。
但是,您应该问问自己,在map/reduce中,一个不可变的键/值应该有什么好处。在JoshuaBloch的高效java第15条中,他指出不可变类更易于设计、实现和使用。他是对的,因为hadoop的reducer是最糟糕的可变性示例:

void reduce(IntWritable key, Iterable<Text> values, Context context) ...

iterable中的每个值都引用 same 共享对象。因此,如果他们将自己的值缓冲到一个正常的集合中,并自问为什么它总是保留相同的值,许多人就会感到困惑。
最后,它归结为性能(cpu和内存——想象一下一个键的数十亿个值对象必须驻留在ram中)与简单性之间的权衡。

相关问题