我是大数据领域的新手,正在努力学习hadoop。令我惊讶的是,大数据或hadoop在默认情况下支持不变性,因为我们希望一次写入数据,多次读取数据,而不变性是分布式存储和处理领域的最佳选择。同时,我了解到hadoop中实现可写接口的所有数据类型本质上都是可变的,以支持框架中的序列化。当所有的数据类型都是可变的时,我在这里感到困惑,那么整个hadoop中如何支持不变性呢?这两件事不矛盾吗?提前谢谢你回答我的问题。
lb3vh1jj1#
Hadoop immutable
使用hadoop,所有写入的记录都是不可变的,因为hadoop不支持随机写入。有时这真的很痛苦,但它能很好地适应。您甚至会发现,越来越多的语言重新提出了不可变对象的概念。为什么?嗯,因为可变对象会带来一些问题。首先,可变对象必须处理并发性。这本身就需要额外的编程来确保一个对象一次只能由一个源更新。在更新已写入磁盘的可变对象时,需要重写更改下面的整个文件。而这可能代价高昂。参考-https://streever.atlassian.net/wiki/display/hadoop/2014/03/06/managing+mutable+data+in+an+immutable+big+data+world
Data type mutable
原因是序列化机制。让我们看看代码://版本1.x maprunner#run()k1 key=input.createkey();v1值=input.createvalue();
while (input.next(key, value)) { // map pair to output mapper.map(key, value, output, reporter);
... 所以我们重新使用同一个键/值对示例。为什么?我不知道当时的设计决策,但我认为这是为了减少垃圾对象的数量。请注意,hadoop非常古老,那时的垃圾收集器没有今天的效率高,但是即使在今天,如果您Map数十亿个对象并将它们作为垃圾直接丢弃,在运行时也会有很大的不同。不能使可写类型真正不可变的真正原因是不能将字段声明为final。让我们用intwritable做一个简单的例子:
public class IntWritable implements WritableComparable { private int value; public IntWritable() {} public IntWritable(int value) { set(value); }
... 如果您将其设置为不可变的,那么它肯定不会再与序列化过程一起工作,因为您需要定义final值。这是行不通的,因为键和值是在运行时通过反射示例化的。这需要一个默认构造函数,因此inputformat无法猜测填充最终数据字段所需的参数。因此,重用示例的整个概念显然与不变性的概念相矛盾。但是,您应该问问自己,在map/reduce中,一个不可变的键/值应该有什么好处。在JoshuaBloch的高效java第15条中,他指出不可变类更易于设计、实现和使用。他是对的,因为hadoop的reducer是最糟糕的可变性示例:
void reduce(IntWritable key, Iterable<Text> values, Context context) ...
iterable中的每个值都引用同一个共享对象。因此,如果他们将自己的值缓冲到一个正常的集合中,并自问为什么它总是保留相同的值,许多人就会感到困惑。最后,它归结为性能(cpu和内存——想象一下一个键的数十亿个值对象必须驻留在ram中)与简单性之间的权衡。为什么一个可写的数据类型应该是可变的?
nlejzf6q2#
我认为您可能会混淆hdfs,即存储文件,它们通常只写一次,不支持使用内存对象(可写对象)进行任意覆盖。这些文件可以编辑,因为它们没有提交到磁盘上,而且为每个操作创建一个新的可写文件会很昂贵(考虑到gc成本)。
2条答案
按热度按时间lb3vh1jj1#
使用hadoop,所有写入的记录都是不可变的,因为hadoop不支持随机写入。有时这真的很痛苦,但它能很好地适应。您甚至会发现,越来越多的语言重新提出了不可变对象的概念。为什么?嗯,因为可变对象会带来一些问题。首先,可变对象必须处理并发性。这本身就需要额外的编程来确保一个对象一次只能由一个源更新。在更新已写入磁盘的可变对象时,需要重写更改下面的整个文件。而这可能代价高昂。参考-https://streever.atlassian.net/wiki/display/hadoop/2014/03/06/managing+mutable+data+in+an+immutable+big+data+world
原因是序列化机制。让我们看看代码:
//版本1.x maprunner#run()k1 key=input.createkey();v1值=input.createvalue();
... 所以我们重新使用同一个键/值对示例。为什么?我不知道当时的设计决策,但我认为这是为了减少垃圾对象的数量。请注意,hadoop非常古老,那时的垃圾收集器没有今天的效率高,但是即使在今天,如果您Map数十亿个对象并将它们作为垃圾直接丢弃,在运行时也会有很大的不同。
不能使可写类型真正不可变的真正原因是不能将字段声明为final。让我们用intwritable做一个简单的例子:
... 如果您将其设置为不可变的,那么它肯定不会再与序列化过程一起工作,因为您需要定义final值。这是行不通的,因为键和值是在运行时通过反射示例化的。这需要一个默认构造函数,因此inputformat无法猜测填充最终数据字段所需的参数。因此,重用示例的整个概念显然与不变性的概念相矛盾。
但是,您应该问问自己,在map/reduce中,一个不可变的键/值应该有什么好处。在JoshuaBloch的高效java第15条中,他指出不可变类更易于设计、实现和使用。他是对的,因为hadoop的reducer是最糟糕的可变性示例:
iterable中的每个值都引用同一个共享对象。因此,如果他们将自己的值缓冲到一个正常的集合中,并自问为什么它总是保留相同的值,许多人就会感到困惑。
最后,它归结为性能(cpu和内存——想象一下一个键的数十亿个值对象必须驻留在ram中)与简单性之间的权衡。
为什么一个可写的数据类型应该是可变的?
nlejzf6q2#
我认为您可能会混淆hdfs,即存储文件,它们通常只写一次,不支持使用内存对象(可写对象)进行任意覆盖。这些文件可以编辑,因为它们没有提交到磁盘上,而且为每个操作创建一个新的可写文件会很昂贵(考虑到gc成本)。