Hadoop分布式下的MapReduce流程及HDFS简单使用

来源:互联网 发布:mac怎么全屏 编辑:程序博客网 时间:2024/05/16 18:58

        上一篇文章我们已经进行了伪分布式配置,也通过几个例子,看到了如何在伪分布式下进行MapReduce操作。今天的文章主要看看在分布式下的MapReduce是如何工作的,然后通过一个小例子,看看Java操作HDFS的方式。

上图是分布式下MapReduce的执行流程,可以看到除了map和reduce之外,还有很多的步骤,这些步骤,我们或多或少的都可以通过配置或者编码的方式对其进行控制,这也是我们对MapReduce进行性能调优的手段。


  1. 输入文件被上传到HDFS之后,会被分片,默认Hadoop集群会保存每个分片的三个副本(伪分布式下我们设置为只有一个副本),如果按照上图来看,在HDFS中会分别有3个spilt1,3个spilt2和3个spilt3。这是为了通过数据冗余保证数据存储的可靠性,当数据出现问题是,可进行恢复。分片的大小默认为HDSF文件块的大小(128M),这样可以有更好的性能。


  2. Hadoop会为每一个spilt分配一个map任务,也就是说,spilt的数目决定了map任务的数目。分配过程遵循一定的原则,首先,如果保存spilt数据的节点处于空闲状态,那么就在这个节点上执行map任务;但是,如果数据存储的节点正在执行其他的任务,那么Hadoop会找数据节点同一个机架中距离最近的空闲节点执行map任务;最后,如果上面的情况都无法满足,就只好跨机架执行map任务了。总的目的就是为了尽可能减少数据的传输,优化性能。


  3. 这样,map任务就分别在各自的节点中并发运行了,这时会对map任务的输出进行排序。这里就需要注意了,由于文件分片只有文件的一部分数据,map处理后的排序是分别针对各自的处理结果进行的,也就是说,这里排序后的结果是部分排序,并不是对输入文件所有数据的排序。


    如果需要对整个文件排序,也是有方法的,一种是阻止Hadoop对文件进行分片,还有一种方式是将分片后的文件聚合后,交给一个map任务处理。


  4. 为了优化性能,map之后的结果是在内存中进行排序的,这时候没有必要将结果写入到磁盘上,但是,reduce需要从磁盘上获取数据,数据写入磁盘的操作被推后到merge阶段,各个map任务处理后的结果,被复制到reduce任务所在的节点,在merge阶段写入磁盘,进而reduce运行,输出结果。reduce任务的数量可以配置,默认为1,如果有多个reduce任务,会在各自的节点上生成结果的分区。


以上就是MapReduce在分布式情况下的运行过程,我们再来看看如何操作HDFS,上一篇文章中,我们使用命令行操作了HDFS,今天看看如何用Java代码实现。我们使用一个简单的例子,将一个字符串写入到HDFS,然后再读取出来显示到终端。

package com.yjp.hdfs;import java.net.URI;import org.apache.hadoop.conf.Configuration;import org.apache.hadoop.fs.FSDataInputStream;import org.apache.hadoop.fs.FSDataOutputStream;import org.apache.hadoop.fs.FileSystem;import org.apache.hadoop.fs.Path;import org.apache.hadoop.io.IOUtils;public class HDFSEcho {// yjp替换为你的用户名private static final URI TMP_URI = URI.create("hdfs://localhost/user/yjp/temp");public static void main(String[] args) throws Exception {if (args.length != 1) {System.out.println("Usage: HDFSEcho string");System.exit(1);}String echoString = args[0] + "\n";// 通过URI创建FileSystem,由于是hdfs,会返回代表HDFS的实例Configuration conf = new Configuration();FileSystem fs = FileSystem.get(TMP_URI, conf);FSDataOutputStream out = null;FSDataInputStream in = null;try {// 写入文件Path path = new Path(TMP_URI);out = fs.create(path);out.writeUTF(echoString);IOUtils.closeStream(out);//从文件读取并输出in = fs.open(path);IOUtils.copyBytes(in, System.out, conf);IOUtils.closeStream(in);//删除文件fs.delete(path, true);} finally {IOUtils.closeStream(out);IOUtils.closeStream(in);}}}
打包为jar文件,记得启动hadoop的后台进程,然后运行试试。

hadoop jar 你的包名.HDFSEcho "Hello HDFS!"


输出为

Hello HDFS!


这部分代码在hdfs包中。


原创粉丝点击