发布网友 发布时间:2022-04-23 03:30
共1个回答
热心网友 时间:2022-04-14 06:40
众所周知,一个“常见”的MapRece程序的Map阶段,是把输入文件分割成很多份,然后一行一行读取,然后进行编程操作。但是这个说法实际上是不严谨的。实际上,在一个“常见”的MapRece任务的Map阶段,启动时是做了以下步骤:
1. 把输入文件分割成M块,一台机器负责其中的几块,这一块叫一个“输入分片”
2. 对于每一块,启动一个任务,运行一个子任务,然后把这一块里面的每一行,一行行输入到Map方法中
这里M的决定十分的复杂,有很多因素能够影响它。例如,若HDFS是按照M作为一块存储数据的,那么较好的想法就是不要分割这里面的数据块,那么上面M个块的大小有可能会被设为M。
而这里就会遇到两个问题:
1. 对于某一行输入数据,我该分配这个数据给这M个任务中的哪一个?这些任务又由哪台机器负责处理?
2. 如果发生了某一行输入数据,一半在机器A存放,而另一半在机器B存放,怎么搞?
对于第一个问题,一个比较好的解决方法是,谁有数据谁去做。例如有一行数据,在设置三个复本的情况下,它可能存放于机器A,B,C中,那么我们可以指定这行数据(甚至其所属的块)由机器A去做(实际上更复杂)。
对于第二个问题,最简单的方法就是,在开始的时候,重新划分一下输入分片,然后让某台机器把那半行数据给另一台机器。
而这在“常见”的情况中,是通过记录以下信息实现的:
1. 输入分片所在的文件
2. 输入分片的偏移量
3. 输入分片的长度
4. 输入分片所在机器
而通过这种方法,系统就可以通过上面的信息告诉负责这一个输入分片的机器,要去哪里读取数据。然后,启动的子任务就会把这一个输入分片按行分割,然后同样用偏移量的方法,一行行处理数据。在这种情况中,Map方法的输入KEY就是偏移量了。
那么关于能否不按行读取的问题,实际上,这里有一个implement,叫“InputFormat”,而用户在启动MapRece的时候需要指定一个它的一个实现。而通过重写里面的方法,是可以修改读取数据的方式的。上面我说的“常见”的情况,其实就是在没有指定InputFormat的实现的时候,调用的默认方法。
而具体怎么重写这个方法,并不是我想要讨论的。这里我在尽量不涉及源代码的情况下,用相当不严谨但是较为易懂的语言说了这么多,是想说明一件事:在MapRece程序中,网络负载是一个很重要的瓶颈。为什么要尽量用本地的数据进行处理?为什么会有机架感知功能?这实际上就是为了减轻网络负载。不过实际上,即使是本地的数据,在运作的过程中其也是先发送出去,然后兜一圈返回本机再进行计算。
所以:
1. MapRece编程的一大问题,是如何减轻网络负载。
2. HDFS和MapRece架构的设计,确实十分精妙地考虑了这个问题。