`
nudtgk2000
  • 浏览: 71012 次
  • 性别: Icon_minigender_1
  • 来自: 大连
社区版块
存档分类
最新评论

《用 Hadoop 进行分布式并行编程, 第 1 部分——基本概念与安装部署》笔记

阅读更多

MapReduce 计算模型


MapReduce 是 Google 公司的核心计算模型,它将复杂的运行于大规模集群上的并行计算过程高度的抽象到了两个函数,Map 和 Reduce, 这是一个令人惊讶的简单却又威力巨大的模型。适合用 MapReduce 来处理的数据集(或任务)有一个基本要求: 待处理的数据集可以分解成许多小的数据集,而且每一个小数据集都可以完全并行地进行处理
MapReduce 计算流程
图 1. MapReduce 计算流程


图一说明了用 MapReduce 来处理大数据集的过程, 这个 MapReduce 的计算过程简而言之,就是将大数据集分解为成百上千的小数据集,每个(或若干个)数据集分别由集群中的一个结点(一般就是一台普通的计算机)进行处理并生成中间结果,然后这些中间结果又由大量的结点进行合并, 形成最终结果。

计算模型的核心是 Map 和 Reduce 两个函数,这两个函数由用户负责实现 ,功能是按一定的映射规则将输入的 <key, value> 对转换成另一个或一批 <key, value> 对输出。

表一 Map 和 Reduce 函数
函数输入输出说明MapReduce
<k1, v1> List(<k2,v2>) 1. 将小数据集进一步解析成一批 <key,value> 对,输入 Map 函数中进行处理。
2. 每一个输入的 <k1,v1> 会输出一批 <k2,v2>。 <k2,v2> 是计算的中间结果。
<k2,List(v2)> <k3,v3> 输入的中间结果 <k2,List(v2)> 中的 List(v2) 表示是一批属于同一个 k2 的 value
以一个计算文本文件中每个单词出现的次数的程序为例,<k1,v1> 可以是 <行在文件中的偏移位置, 文件中的一行>,经 Map 函数映射之后,形成一批中间结果 <单词,出现次数>, 而 Reduce 函数则可以对中间结果进行处理,将相同单词的出现次数进行累加,得到每个单词的总的出现次数。

基于 MapReduce 计算模型编写分布式并行程序非常简单,程序员的主要编码工作就是实现 Map 和 Reduce 函数 ,其它的并行编程中的种种复杂问题,如分布式存储,工作调度,负载平衡,容错处理,网络通信等,均由 MapReduce 框架(比如 Hadoop )负责处理。


数据分布存储
Hadoop 中的分布式文件系统 HDFS 由一个管理结点 ( NameNode )和N个数据结点 ( DataNode )组成 ,每个结点均是一台普通的计算机。在使用上同我们熟悉的单机上的文件系统非常类似,一样可以建目录,创建,复制,删除文件,查看文件内容等。但其底层实现上是把文件切割成 Block,然后这些 Block 分散地存储于不同的 DataNode 上,每个 Block 还可以复制数份存储于不同的 DataNode 上 ,达到容错容灾之目的。NameNode 则是整个 HDFS 的核心,它通过维护一些数据结构,记录了每一个文件被切割成了多少个 Block,这些 Block 可以从哪些 DataNode 中获得,各个 DataNode 的状态等重要信息 。如果你想了解更多的关于 HDFS 的信息,可进一步阅读参考资料: The Hadoop Distributed File System:Architecture and Design

 

分布式并行计算

Hadoop 中有一个作为主控的 JobTracker 用于调度和管理其它的 TaskTracker , 将 Map 任务和 Reduce 任务分发给空闲的 TaskTracker, 让这些任务并行运行,并负责监控任务的运行情况。如果某一个 TaskTracker 出故障了,JobTracker 会将其负责的任务转交给另一个空闲的 TaskTracker 重新运行。 JobTracker 可以运行于集群中任一台计算机上。TaskTracker 负责执行任务,必须运行于 DataNode 上 ,即 DataNode 既是数据存储结点,也是计算结点。

 

分布存储与并行计算

图2 分布存储与并行计算

 

任务粒度

把原始大数据集切割成小数据集时,通常让小数据集小于或等于 HDFS 中一个 Block 的大小(缺省是 64M),这样能够保证一个小数据集位于一台计算机上,便于本地计算。有 M 个小数据集待处理,就启动 M 个 Map 任务,注意这 M 个 Map 任务分布于 N 台计算机上并行运行 ,Reduce 任务的数量 R 则可由用户指定。

Partition

把 Map 任务输出的中间结果按 key 的范围划分成 R 份( R 是预先定义的 Reduce 任务的个数),划分时通常使用 hash 函数如: hash(key) mod R ,这样可以保证某一段范围内的 key,一定是由一个 Reduce 任务来处理,可以简化 Reduce 的过程。

Combine

在 partition 之前,还可以将中间结果中有相同 key的 <key, value> 对合并成一对。combine 的过程与 Reduce 的过程类似,很多情况下就可以直接使用 Reduce 函数,但 combine 是作为 Map 任务的一部分,在执行完 Map 函数后紧接着执行的(?是否就是说combine是在对本地中间结果执行的)。Combine 能够减少中间结果中 <key, value> 对的数目,从而减少网络流量。


Map 任务的中间结果在做完 Combine 和 Partition 之后,以文件形式存于本地磁盘。中间结果文件的位置会通知主控 JobTracker, JobTracker 再通知 Reduce 任务到哪一个 DataNode 上去取中间结果。注意所有的 Map 任务产生中间结果均按其 Key 用同一个 Hash 函数划分成了 R 份,R 个 Reduce 任务各自负责一段 Key 区间。每个 Reduce 需要向许多个 Map 任务结点取得落在其负责的 Key 区间内的中间结果,然后执行 Reduce 函数,形成一个最终的结果文件。

 

 

任务管道

有 R 个 Reduce 任务,就会有 R 个最终结果,很多情况下这 R 个最终结果并不需要合并成一个最终结果。因为这 R 个最终结果又可以做为另一个计算任务的输入,开始另一个并行计算任务。

 

Hadoop 初体验

……
修改 conf/hadoop-env.sh 文件,在其中设置 JAVA_HOME 环境变量: export JAVA_HOME="C:\Program Files\Java\jdk1.5.0_01” (因为路径中 Program Files 中间有空格,一定要用双引号将路径引起来)
……
注意事项:运行 bin/hadoop jar hadoop-0.16.0-examples.jar wordcount test-in test-out 时,务必注意第一个参数是 jar , 不是 -jar , 当你用 -jar 时,不会告诉你是参数错了,报告出来的错误信息是:Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/hadoop/util/ProgramDriver, 笔者当时以为是 classpath 的设置问题,浪费了不少时间。通过分析 bin/hadoop 脚本可知,-jar 并不是 bin/hadoop 脚本定义的参数,此脚本会把 -jar 作为 Java 的参数,Java 的-jar 参数表示执行一个 Jar 文件(这个 Jar 文件必须是一个可执行的 Jar,即在 MANIFEST 中定义了主类), 此时外部定义的 classpath 是不起作用的,因而会抛出 java.lang.NoClassDefFoundError 异常。而 jar 是 bin/hadoop 脚本定义的参数,会调用 Hadoop 自己的一个工具类 RunJar,这个工具类也能够执行一个 Jar 文件,并且外部定义的 classpath 有效。
……

 

伪分布式运行模式

用不同的 Java 进程模仿分布式运行中的各类结点 ( NameNode, DataNode, JobTracker, TaskTracker, Secondary NameNode ), Secondary NameNode 作为 NameNode 的备份。TaskTracker 必须运行在 DataNode 上,这样便于数据的本地计算。JobTracker 和 NameNode 则无须在同一台机器上。

(1) 修改 conf/hadoop-site.xml。注意 conf/hadoop-default.xml 中是 Hadoop 缺省的参数,你可以通过读此文件了解 Hadoop 中有哪些参数可供配置,但不要修改此文件。conf/hadoop-site.xml 修改的参数值会覆盖 conf/hadoop-default.xml 的同名参数。

<configuration>
  <property>
    <name>fs.default.name</name>
    <value>localhost:9000</value>
  </property>
  <property>
    <name>mapred.job.tracker</name>
    <value>localhost:9001</value>
  </property>
  <property>
    <name>dfs.replication</name>
    <value>1</value>
  </property>
</configuration>
 

参数 fs.default.name 指定 NameNode 的 IP 地址和端口号。缺省值是 file:///, 表示使用本地文件系统, 用于单机非分布式模式。此处我们指定使用运行于本机 localhost 上的 NameNode。

参数 mapred.job.tracker 指定 JobTracker 的 IP 地址和端口号。缺省值是 local, 表示在本地同一 Java 进程内执行 JobTracker 和 TaskTracker, 用于单机非分布式模式。此处我们指定使用运行于本机 localhost 上的 JobTracker ( 用一个单独的 Java 进程做 JobTracker )。

参数 dfs.replication 指定 HDFS 中每个 Block 被复制的次数,起数据冗余备份的作用。 在典型的生产系统中,这个数常常设置为3。

……

启动完成之后,通过 ps –ef 应该可以看到启动了5个新的 java 进程。

……

故障诊断

(1) 执行 $ bin/start-all.sh 启动 Hadoop 进程后,会启动5个 java 进程, 同时会在 /tmp 目录下创建五个 pid 文件记录这些进程 ID 号。通过这五个文件,可以得知 namenode, datanode, secondary namenode, jobtracker, tasktracker 分别对应于哪一个 Java 进程。当你觉得 Hadoop 工作不正常时,可以首先查看这5个 java 进程是否在正常运行。

(2) 使用 web 接口。访问 http://localhost:50030 可以查看 JobTracker 的运行状态。访问 http://localhost:50060 可以查看 TaskTracker 的运行状态。访问 http://localhost:50070 可以查看 NameNode 以及整个分布式文件系统的状态,浏览分布式文件系统中的文件以及 log 等。

(3) 查看 ${HADOOP_HOME}/logs 目录下的 log 文件,namenode, datanode, secondary namenode, jobtracker, tasktracker 各有一个对应的 log 文件,每一次运行的计算任务也有对应用 log 文件。分析这些 log 文件有助于找到故障原因。

 

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics