MapReduce框架结构简介(一)--手动实现hadoop wordcount功能

本文介绍了使用Hadoop的MapReduce框架手动实现单词统计的方法。先介绍了运行环境,接着阐述MapReduce的概念、框架结构及运行机制,说明了编程规范,最后详细说明了单词统计需求的实现步骤,包括编写map和reduce代码、提交任务等。

环境介绍

  • hadoop-2.6.4
  • jdk1.7
  • centos6.5-x86

MapReduce简介

Mapreduce是一个分布式运算程序的编程框架,是用户开发“基于hadoop的数据分析应用”的核心框架;
Mapreduce核心功能是将用户编写的业务逻辑代码和自带默认组件整合成一个完整的分布式运算程序,并发运行在一个hadoop集群上。

MapReduce框架结构及核心运行机制

  • 结构
    • 一个完整的mapreduce程序在分布式运行时有三类实例进程
      • 1、MRAppMaster:负责整个程序的过程调度及状态协调
      • 2、mapTask:负责map阶段的整个数据处理流程
      • 3、ReduceTask:负责reduce阶段的整个数据处理流程
  • MapRedce运行的流程解析
    • 1、 一个mr程序启动的时候,最先启动的是MRAppMaster,MRAppMaster启动后根据本次job的描述信息,计算出需要的maptask实例数量,然后向集群申请机器启动相应数量的maptask进程
    • 2、 maptask进程启动之后,根据给定的数据切片范围进行数据处理,主体流程为:
      • 1)利用客户指定的inputformat来获取RecordReader读取数据,形成输入KV对
      • 2)将输入KV对传递给客户定义的map()方法,做逻辑运算,并将map()方法输出的KV对收集到缓存
      • 3)将缓存中的KV对按照K分区排序后不断溢写到磁盘文件
    • 3、 MRAppMaster监控到所有maptask进程任务完成之后,会根据客户指定的参数启动相应数量的reducetask进程,并告知reducetask进程要处理的数据范围(数据分区)
    • 4、Reducetask进程启动之后,根据MRAppMaster告知的待处理数据所在位置,从若干台maptask运行所在机器上获取到若干个maptask输出结果文件,并在本地进行重新归并排序,然后按照相同key的KV为一个组,调用客户定义的reduce()方法进行逻辑运算,并收集运算输出的结果KV,然后调用客户指定的outputformat将结果数据输出到外部存储

MapReduce框架编程规范

  • (1)用户编写的程序分成三个部分:Mapper,Reducer,Driver(提交运行mr程序的客户端)
  • (2)Mapper的输入数据是KV对的形式(KV的类型可自定义)
  • (3)Mapper的输出数据是KV对的形式(KV的类型可自定义)
  • (4)Mapper中的业务逻辑写在map()方法中
  • (5)map()方法(maptask进程)对每一个<K,V>调用一次
  • (6)Reducer的输入数据类型对应Mapper的输出数据类型,也是KV
  • (7)Reducer的业务逻辑写在reduce()方法中
  • (8)Reducetask进程对每一组相同k的<k,v>组调用一次reduce()方法
  • (9)用户自定义的Mapper和Reducer都要继承各自的父类
  • (10) 整个程序需要一个Drvier来进行提交,提交的是一个描述了各种必要信息的job对象

wordcount单词统计需求

在一堆给定的文本文件中统计输出每一个单词出现的总次数

  • wordcount 程序在集群执行过程示意图
    在这里插入图片描述
  • 单词统计map的编写,需要继承org.apache.hadoop.mapreduce.Mapper
import java.io.IOException;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;
/**
 * KEYIN:默认情况下,是mr框架所读到的一行文本的起始偏移量,Long
 * 但是hadoop中有自己的更精简的序列化接口,所以不直接用Long,而用LongWritable
 * VALUEIN:默认情况下,是mr框架所读到的一行文本的内容,String 用Text
 * KEYOUT:是用户自己定义逻辑处理完成之后输出数据中的Key,此处是单词,String 用Text
 * VALUEOUT:是用户自定义逻辑处理完成之后输出数据中的value,此处是单词次数,Integer  用IntWritable
 * @author potter
 */
public class WordcountMapper extends Mapper<LongWritable, Text, Text, IntWritable>{
	/**
	 * map阶段的业务逻辑就写在自定义的map()方法中
	 * maptask会对每一行输入数据调用一次我们自定义的map()方法
	 */
	@Override
	protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
        //将maptask传给我们的文本内容先转换成String
		String line = value.toString();
		//根据空格将单词这一行切分成单词
		String[] words =  line.split(" ");
		//将单词输出为<单词,1>
		for(String word : words ){
			//将单词作为key,将次数1作为value,以便后续的数据分发,可以根据单词分发,以便于相同的单词会到相同的reduce task中
			context.write(new Text(word), new IntWritable(1));
		}
	}
}
  • 单词统计reduce的编写 需继承org.apache.hadoop.mapreduce.Reducer
import java.io.IOException;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer;
/**
 * KEYIN,VALUEIN对应mapper输出的KEYOUT,VALUEOUT类型
 * KEYOUT,VALUEOUT是自定义reduce逻辑处理结果输出数据类型
 * KEYUOUT是单词
 * VALUEOUT是总次数
 * @author potter
 */
public class WordcountReducer extends Reducer<Text,IntWritable,Text,IntWritable>{
	/**<apple,1><apple,1><apple,1><apple,1><apple,1><apple,1><apple,1><apple,1>
	 * <banana,1><banana,1><banana,1><banana,1><banana,1><banana,1><banana,1>
	 * <hello,1><hello,1><hello,1><hello,1><hello,1><hello,1><hello,1><hello,1>
	 * 入参参数,key是一组相同单词KV对的key
	 */
	@Override
	protected void reduce(Text key, Iterable<IntWritable> values,Context context)throws IOException, InterruptedException {
		int count = 0 ;
		for(IntWritable value : values){
			count += value.get();
		}
		context.write(key, new IntWritable(count));
	}
}
  • yarn客户端用于提交task
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
/**
 * 相当于yarn集群的客户端
 * 需要在此封装我们的mr程序的相关运行参数,指定jar包
 * 最后提交给yarn
 * @author potter
 *
 */
public class WordcountDriver {
	public static void main(String args[]) throws Exception{
		Configuration conf = new Configuration();
		Job job = Job.getInstance(conf);
		job.setJarByClass(WordcountDriver.class);
		
		//指定本业务job要使用的Mapper/Reduce业务类
		job.setMapperClass(WordcountMapper.class);
		job.setReducerClass(WordcountReducer.class);
		
		//指定mapper输出数据的kv类型
		job.setMapOutputKeyClass(Text.class);
		job.setMapOutputValueClass(IntWritable.class);
		
		//指定最终输出的数据的kv类型
		job.setOutputKeyClass(Text.class);
		job.setOutputValueClass(IntWritable.class);
		
		//指定job的输入的原始文件所在目录
		FileInputFormat.setInputPaths(job, new Path(args[0]));
		//指定job的输出结果所在目录
		FileOutputFormat.setOutputPath(job, new Path(args[1]));
		
		//将job中配置的相关参数,以及job所用的java类所在的jar包,提交给yarn去运行
	    boolean response = job.waitForCompletion(true);
	    System.exit(response?0:1);
	}
}
  • 将该项目export->jar file 并命名为wordcount.jar 并放到hadoop集群任意一台服务器上
  • 通过 hadoop fs -mkdir -p /wordcount/input/ 在服务器上新建目录存放用于统计的文本文件
  • 通过 hadoop fs -put [文件名] 命令 ,上传文本到新建的input目录下
  • 通过 hadoop jar [wordcount jar包名称 ] [Driver主类(yarn客户端)路径名] [待统计文本地址] [输出文本地址] 运行 jar包
  • 集群启动map和reduce执行任务
  • 执行完成后 生成对应的统计信息文件 默认输出单词是有序的
    在这里插入图片描述
<think>好的,我现在需要帮助用户解决Hadoop运行WordCount时出现的“找不到或无法加载主类org.apache.hadoop.mapreduce.v2.app.MRAppMaster”错误。首先,我要回顾之前的对话和用户提供的引用内容,确保解决方案的准确性和全面性。 用户提到之前给出的回答中引用了四个参考资料,其中引用了不同的解决方法,比如检查JAR包路径、配置类路径、版本匹配以及修改mapred-site.xml文件中的环境变量设置。现在用户再次遇到同样的问题,需要更详细的解决方案。 首先,我需要确认这个错误的主要原因。根据引用[3],问题可能出在Hadoop的配置上,特别是缺少HADOOP_MAPRED_HOME的环境变量设置。同时,引用[2]指出需要确保mapred-site.xml中的类路径配置正确,路径分隔符应该是逗号而不是冒号。此外,版本不匹配也可能导致这个问题,如引用[1]和[4]提到的JAR包版本与实际Hadoop安装版本不致。 接下来,我需要整理出具体的解决步骤。用户可能已经尝试过些方法,但问题依然存在,所以需要更详细的指导。可能的步骤包括: 1. 验证JAR包路径和版本:确保使用的示例JAR文件确实存在,并且版本号与Hadoop安装版本完全致。例如,用户使用的是3.1.4版本的JAR,而Hadoop安装可能是3.1.3,这会导致问题。 2. 检查类路径配置:在mapred-site.xml中添加正确的类路径,确保路径分隔符是逗号,并且所有必要的Hadoop库路径都被包含进去。引用[2]和[3]都提到了这点,可能需要用户再次检查配置是否正确。 3. 添加环境变量配置:在mapred-site.xml中设置HADOOP_MAPRED_HOME的环境变量,确保MapReduce应用能够找到所需的类。引用[3]提供了具体的XML配置代码,需要用户正确添加到配置文件中。 4. 重启Hadoop集群:任何配置文件的修改都需要重启集群才能生效,用户需要执行stop-all.sh和start-all.sh来重启服务。 5. 检查HDFS安全模式:如果HDFS处于安全模式,可能导致应用无法正常运行,用户需要确保退出安全模式。 此外,用户可能遇到的常见错误包括路径错误、权限问题或输出目录已存在,这些也需要在解决方案中提到,帮助用户全面排查。 最后,生成的相关问题需要与用户当前的问题相关,例如如何验证集群配置、处理数据倾斜或安全模式的相关问题,这有助于用户进步理解和解决其他潜在的问题。 现在需要将这些思考整理成结构化的解决方案,确保步骤清晰,引用正确,并且语言简洁明了,帮助用户步步解决问题。</think>#### Hadoop运行WordCount时主类无法加载的深度解决方案 --- ### 、核心问题根源 出现$org.apache.hadoop.mapreduce.v2.app.MRAppMaster$类加载失败的**根本原因**是Hadoop运行时无法定位MapReduce框架的核心依赖库,具体表现为以下三类问题[^2][^3]: 1. **环境变量缺失**:`mapred-site.xml`未配置`HADOOP_MAPRED_HOME`环境变量 2. **类路径错误**:`mapreduce.application.classpath`配置未包含完整Hadoop库路径 3. **版本冲突**:示例JAR包版本与Hadoop实际版本不匹配(如使用$3.1.4$示例JAR但运行在$3.1.3$集群) --- ### 二、分步解决方案 #### 1. 验证版本致性(关键步骤) ```bash # 查看Hadoop实际版本(注意输出中的版本号) hadoop version | grep "Hadoop" # 检查示例JAR版本(必须完全致) ls $HADOOP_HOME/share/hadoop/mapreduce/hadoop-mapreduce-examples-*.jar ``` *示例输出*: ``` Hadoop 3.1.3 hadoop-mapreduce-examples-3.1.3.jar # 正确 hadoop-mapreduce-examples-3.1.4.jar # 错误(需删除或替换) ``` #### 2. 修复环境变量配置(核心配置) 修改`mapred-site.xml`(需sudo权限): ```bash sudo vim $HADOOP_HOME/etc/hadoop/mapred-site.xml ``` 添加以下**必须配置**(注意保持原有配置): ```xml <!-- 设置MapReduce应用主类环境变量 --> <property> <name>yarn.app.mapreduce.am.env</name> <value>HADOOP_MAPRED_HOME=${HADOOP_HOME}</value> </property> <property> <name>mapreduce.map.env</name> <value>HADOOP_MAPRED_HOME=${HADOOP_HOME}</value> </property> <property> <name>mapreduce.reduce.env</name> <value>HADOOP_MAPRED_HOME=${HADOOP_HOME}</value> </property> <!-- 设置完整类路径(示例路径,需根据实际安装路径修改) --> <property> <name>mapreduce.application.classpath</name> <value> /opt/hadoop-3.1.3/etc/hadoop, /opt/hadoop-3.1.3/share/hadoop/common/*, /opt/hadoop-3.1.3/share/hadoop/common/lib/*, /opt/hadoop-3.1.3/share/hadoop/hdfs/*, /opt/hadoop-3.1.3/share/hadoop/hdfs/lib/*, /opt/hadoop-3.1.3/share/hadoop/mapreduce/*, /opt/hadoop-3.1.3/share/hadoop/mapreduce/lib/*, /opt/hadoop-3.1.3/share/hadoop/yarn/*, /opt/hadoop-3.1.3/share/hadoop/yarn/lib/* </value> </property> ``` *关键细节*:路径分隔符必须使用`,`而非`:`,且需要包含所有Hadoop组件的库路径[^2] #### 3. 应用配置并验证 ```bash # 重启Hadoop集群(必须步骤) stop-all.sh && start-all.sh # 验证MRAppMaster类可访问 hadoop classpath | grep MRAppMaster # 预期输出应包含MRAppMaster.class的路径 ``` #### 4. 执行WordCount验证 ```bash # 强制清理旧输出目录(重要) hdfs dfs -rm -r /wordcount/output # 使用绝对路径执行(避免路径解析错误) hadoop jar $HADOOP_HOME/share/hadoop/mapreduce/hadoop-mapreduce-examples-$(hadoop version | awk '/Hadoop/{print $2}').jar \ wordcount /wordcount/input /wordcount/output ``` *技巧*:`$(hadoop version...)`自动匹配当前Hadoop版本,避免手动输入版本号 --- ### 三、高级排查方法 若仍出现错误,可通过以下方式定位问题: 1. **查看YARN日志**: ```bash # 获取应用ID后查看日志 yarn logs -applicationId <application_id> | grep -C 10 MRAppMaster ``` 2. **手动验证类加载**: ```bash # 检查类是否存在于Hadoop类路径 find $HADOOP_HOME -name "MRAppMaster.class" # 正确输出示例: # /opt/hadoop-3.1.3/share/hadoop/mapreduce/hadoop-mapreduce-client-app-3.1.3.jar ``` 3. **使用调试模式**: ```bash export HADOOP_ROOT_LOGGER=DEBUG,console hadoop jar [...] 2>&1 | grep -i classpath ``` --- ### 四、配置优化建议 1. **创建软链接**避免版本冲突: ```bash ln -s hadoop-mapreduce-examples-3.1.3.jar hadoop-mapreduce-examples.jar # 后续可简化命令为: hadoop jar $HADOOP_HOME/share/hadoop/mapreduce/hadoop-mapreduce-examples.jar wordcount ... ``` 2. **使用环境变量**增强可移植性: ```bash # 在~/.bashrc中添加 export HADOOP_EXAMPLES_JAR=$(ls $HADOOP_HOME/share/hadoop/mapreduce/hadoop-mapreduce-examples-*.jar) # 执行命令简化为: hadoop jar $HADOOP_EXAMPLES_JAR wordcount ... ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值