Hadoop简介(1):什么是Map/Reduce

本文深入浅出地介绍了Hadoop及其核心组件MapReduce的工作原理和技术细节,通过生动的实例帮助读者理解分布式计算的基本概念。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Hadoop简介

Hadoop就是一个实现了Google云计算系统的开源系统,包括并行计算模型Map/Reduce,分布式文件系统HDFS,以及分布式数据库Hbase,同时Hadoop的相关项目也很丰富,包括ZooKeeper,Pig,Chukwa,Hive,Hbase,Mahout,flume等.

这里详细分解这里面的概念让大家通过这篇文章了解到底是什么hadoop:




1.什么是Map/Reduce,看下面的各种解释:


(1)MapReduce是hadoop的核心组件之一,hadoop要分布式包括两部分,一是分布式文件系统hdfs,一部是分布式计算框,就是mapreduce,缺一不可,也就是说,可以通过mapreduce很容易在hadoop平台上进行分布式的计算编程。

(2)Mapreduce是一种编程模型,是一种编程方法,抽象理论。


(3)下面是一个关于一个程序员是如何个妻子讲解什么是MapReduce?文章很长请耐心的看。


我问妻子:“你真的想要弄懂什么是MapReduce?” 她很坚定的回答说“是的”。 因此我问道:


我: 你是如何准备洋葱辣椒酱的?(以下并非准确食谱,请勿在家尝试)


妻子: 我会取一个洋葱,把它切碎,然后拌入盐和水,最后放进混合研磨机里研磨。这样就能得到洋葱辣椒酱了。



妻子: 但这和MapReduce有什么关系?

我: 你等一下。让我来编一个完整的情节,这样你肯定可以在15分钟内弄懂MapReduce.


妻子: 好吧。


我:现在,假设你想用薄荷、洋葱、番茄、辣椒、大蒜弄一瓶混合辣椒酱。你会怎么做呢?


妻子: 我会取薄荷叶一撮,洋葱一个,番茄一个,辣椒一根,大蒜一根,切碎后加入适量的盐和水,再放入混合研磨机里研磨,这样你就可以得到一瓶混合辣椒酱了。


我: 没错,让我们把MapReduce的概念应用到食谱上。Map和Reduce其实是两种操作,我来给你详细讲解下。

Map(映射): 把洋葱、番茄、辣椒和大蒜切碎,是各自作用在这些物体上的一个Map操作。所以你给Map一个洋葱,Map就会把洋葱切碎。 同样的,你把辣椒,大蒜和番茄一一地拿给Map,你也会得到各种碎块。 所以,当你在切像洋葱这样的蔬菜时,你执行就是一个Map操作。 Map操作适用于每一种蔬菜,它会相应地生产出一种或多种碎块,在我们的例子中生产的是蔬菜块。在Map操作中可能会出现有个洋葱坏掉了的情况,你只要把坏洋葱丢了就行了。所以,如果出现坏洋葱了,Map操作就会过滤掉坏洋葱而不会生产出任何的坏洋葱块。


Reduce(化简):在这一阶段,你将各种蔬菜碎都放入研磨机里进行研磨,你就可以得到一瓶辣椒酱了。这意味要制成一瓶辣椒酱,你得研磨所有的原料。因此,研磨机通常将map操作的蔬菜碎聚集在了一起。

妻子: 所以,这就是MapReduce?


我: 你可以说是,也可以说不是。 其实这只是MapReduce的一部分,MapReduce的强大在于分布式计算。


妻子: 分布式计算? 那是什么?请给我解释下吧。


我: 没问题。

我: 假设你参加了一个辣椒酱比赛并且你的食谱赢得了最佳辣椒酱奖。得奖之后,辣椒酱食谱大受欢迎,于是你想要开始出售自制品牌的辣椒酱。假设你每天需要生产10000瓶辣椒酱,你会怎么办呢?


妻子: 我会找一个能为我大量提供原料的供应商。


我:是的..就是那样的。那你能否独自完成制作呢?也就是说,独自将原料都切碎? 仅仅一部研磨机又是否能满足需要?而且现在,我们还需要供应不同种类的辣椒酱,像洋葱辣椒酱、青椒辣椒酱、番茄辣椒酱等等。


妻子: 当然不能了,我会雇佣更多的工人来切蔬菜。我还需要更多的研磨机,这样我就可以更快地生产辣椒酱了。
我:没错,所以现在你就不得不分配工作了,你将需要几个人一起切蔬菜。每个人都要处理满满一袋的蔬菜,而每一个人都相当于在执行一个简单的Map操作。每一个人都将不断的从袋子里拿出蔬菜来,并且每次只对一种蔬菜进行处理,也就是将它们切碎,直到袋子空了为止。
这样,当所有的工人都切完以后,工作台(每个人工作的地方)上就有了洋葱块、番茄块、和蒜蓉等等。


妻子:但是我怎么会制造出不同种类的番茄酱呢?


我:现在你会看到MapReduce遗漏的阶段—搅拌阶段。MapReduce将所有输出的蔬菜碎都搅拌在了一起,这些蔬菜碎都是在以key为基础的 map操作下产生的。搅拌将自动完成,你可以假设key是一种原料的名字,就像洋葱一样。 所以全部的洋葱keys都会搅拌在一起,并转移到研磨洋葱的研磨器里。这样,你就能得到洋葱辣椒酱了。同样地,所有的番茄也会被转移到标记着番茄的研磨器里,并制造出番茄辣椒酱。


(4)上面都是从理论上来说明什么是MapReduce,那么咱们在MapReduce产生的过程和代码的角度来理解这个问题。
如果想统计下过去10年计算机论文出现最多的几个单词,看看大家都在研究些什么,那收集好论文后,该怎么办呢? 

  方法一:

      我可以写一个小程序,把所有论文按顺序遍历一遍,统计每一个遇到的单词的出现次数,最后就可以知道哪几个单词最热门了。 这种方法在数据集比较小时,是非常有效的,而且实现最简单,用来解决这个问题很合适。 

 方法二:

       写一个多线程程序,并发遍历论文。 
  这个问题理论上是可以高度并发的,因为统计一个文件时不会影响统计另一个文件。当我们的机器是多核或者多处理器,方法二肯定比方法一高效。但是写一个多线程程序要比方法一困难多了,我们必须自己同步共享数据,比如要防止两个线程重复统计文件。 

方法三:

      把作业交给多个计算机去完成。 
  我们可以使用方法一的程序,部署到N台机器上去,然后把论文集分成N份,一台机器跑一个作业。这个方法跑得足够快,但是部署起来很麻烦,我们要人工把程序copy到别的机器,要人工把论文集分开,最痛苦的是还要把N个运行结果进行整合(当然我们也可以再写一个程序)。 

  方法四:

      让MapReduce来帮帮我们吧! 

  MapReduce本质上就是方法三,但是如何拆分文件集,如何copy程序,如何整合结果这些都是框架定义好的。我们只要定义好这个任务(用户程序),其它都交给MapReduce。


map函数和reduce函数  


map函数和reduce函数是交给用户实现的,这两个函数定义了任务本身。 

  map函数:接受一个键值对(key-value pair),产生一组中间键值对。MapReduce框架会将map函数产生的中间键值对里键相同的值传递给一个reduce函数。 

  reduce函数:接受一个键,以及相关的一组值,将这组值进行合并产生一组规模更小的值(通常只有一个或零个值)。 

  统计词频的MapReduce函数的核心代码非常简短,主要就是实现这两个函数。 

  map(String key, String value): 

  // key: document name 

  // value: document contents 

  for each word w in value: 

  EmitIntermediate(w, "1"); 

  reduce(String key, Iterator values): 

  // key: a word 

  // values: a list of counts 

  int result = 0; 

  for each v in values: 

  result += ParseInt(v); 

  Emit(AsString(result)); 

  在统计词频的例子里,map函数接受的键是文件名,值是文件的内容,map逐个遍历单词,每遇到一个单词w,就产生一个中间键值对<w, "1">,这表示单词w咱又找到了一个;MapReduce将键相同(都是单词w)的键值对传给reduce函数,这样reduce函数接受的键就是单词w,值是一串"1"(最基本的实现是这样,但可以优化),个数等于键为w的键值对的个数,然后将这些“1”累加就得到单词w的出现次数。最后这些单词的出现次数会被写到用户定义的位置,存储在底层的分布式存储系统(GFS或HDFS)。 




工作原理

 

  
上图是论文里给出的流程图。一切都是从最上方的user program开始的,user program链接了MapReduce库,实现了最基本的Map函数和Reduce函数。图中执行的顺序都用数字标记了。

  1.MapReduce库先把user program的输入文件划分为M份(M为用户定义),每一份通常有16MB到64MB,如图左方所示分成了split0~4;然后使用fork将用户进程拷贝到集群内其它机器上。 

  2.user program的副本中有一个称为master,其余称为worker,master是负责调度的,为空闲worker分配作业(Map作业或者Reduce作业),worker的数量也是可以由用户指定的。 

  3.被分配了Map作业的worker,开始读取对应分片的输入数据,Map作业数量是由M决定的,和split一一对应;Map作业从输入数据中抽取出键值对,每一个键值对都作为参数传递给map函数,map函数产生的中间键值对被缓存在内存中。 

  4.缓存的中间键值对会被定期写入本地磁盘,而且被分为R个区,R的大小是由用户定义的,将来每个区会对应一个Reduce作业;这些中间键值对的位置会被通报给master,master负责将信息转发给Reduce worker。 

  5.master通知分配了Reduce作业的worker它负责的分区在什么位置(肯定不止一个地方,每个Map作业产生的中间键值对都可能映射到所有R个不同分区),当Reduce worker把所有它负责的中间键值对都读过来后,先对它们进行排序,使得相同键的键值对聚集在一起。因为不同的键可能会映射到同一个分区也就是同一个Reduce作业(谁让分区少呢),所以排序是必须的。 

  6.reduce worker遍历排序后的中间键值对,对于每个唯一的键,都将键与关联的值传递给reduce函数,reduce函数产生的输出会添加到这个分区的输出文件中。 

  6.当所有的Map和Reduce作业都完成了,master唤醒正版的user program,MapReduce函数调用返回user program的代码。 

  所有执行完毕后,MapReduce输出放在了R个分区的输出文件中(分别对应一个Reduce作业)。用户通常并不需要合并这R个文件,而是将其作为输入交给另一个MapReduce程序处理。整个过程中,输入数据是来自底层分布式文件系统(GFS)的,中间数据是放在本地文件系统的,最终输出数据是写入底层分布式文件系统(GFS)的。而且我们要注意Map/Reduce作业和map/reduce函数的区别:Map作业处理一个输入数据的分片,可能需要调用多次map函数来处理每个输入键值对;Reduce作业处理一个分区的中间键值对,期间要对每个不同的键调用一次reduce函数,Reduce作业最终也对应一个输出文件。

总结:

通过以上你是否了解什么是MapReduce了那,什么是key,怎么过滤有效数据,怎么得到自己想要的数据。
MapReduce是一种编程思想,可以使用java来实现,C++来实现。Map的作用是过滤一些原始数据,Reduce则是处理这些数据,得到我们想要的结果,比如你想造出番茄辣椒酱。也就是我们使用hadoop,比方来进行日志处理之后,得到我们想要的关心的数据

hadoop jar /opt/program/hadoop-3.1.3/share/hadoop/mapreduce/hadoop-mapreduce-examples-3.1.3.jar words.txt hdfs://hadoop:8020/input hdfs://hadoop1:8020/output/wc Unknown program 'words.txt' chosen. Valid program names are: aggregatewordcount: An Aggregate based map/reduce program that counts the words in the input files. aggregatewordhist: An Aggregate based map/reduce program that computes the histogram of the words in the input files. bbp: A map/reduce program that uses Bailey-Borwein-Plouffe to compute exact digits of Pi. dbcount: An example job that count the pageview counts from a database. distbbp: A map/reduce program that uses a BBP-type formula to compute exact bits of Pi. grep: A map/reduce program that counts the matches of a regex in the input. join: A job that effects a join over sorted, equally partitioned datasets multifilewc: A job that counts words from several files. pentomino: A map/reduce tile laying program to find solutions to pentomino problems. pi: A map/reduce program that estimates Pi using a quasi-Monte Carlo method. randomtextwriter: A map/reduce program that writes 10GB of random textual data per node. randomwriter: A map/reduce program that writes 10GB of random data per node. secondarysort: An example defining a secondary sort to the reduce. sort: A map/reduce program that sorts the data written by the random writer. sudoku: A sudoku solver. teragen: Generate data for the terasort terasort: Run the terasort teravalidate: Checking results of terasort wordcount: A map/reduce program that counts the words in the input files. wordmean: A map/reduce program that counts the average length of the words in the input files. wordmedian: A map/reduce program that counts the median length of the words in the input files. wordstandarddeviation: A map/reduce program that counts the standard deviation of the length of the words in the input files. [root@master hadoop]#
最新发布
03-14
<think>好的,我现在需要解决用户提到的Hadoop命令中的“Unknown program 'words.txt'”错误。用户使用的是Hadoop 3.1.3版本,并且在运行MapReduce示例时遇到了这个问题。首先,我需要理解这个错误的具体原因以及可能的解决方法。 首先,用户提到的错误信息是“Unknown program 'words.txt'”,这可能出现在执行hadoop jar命令时。根据用户提供的引用,特别是引用[1],正确的命令应该是将输入和输出路径作为参数传递,例如: hadoop jar $HADOOP_HOME/share/hadoop/mapreduce/hadoop-mapreduce-examples-3.1.3.jar wordcount /input /output 这里,“wordcount”是程序名,后面跟的是输入路径和输出路径。因此,如果用户在命令中误将输入文件(如words.txt)作为程序名来调用,就会出现“Unknown program”错误。例如,如果用户错误地写成: hadoop jar examples.jar words.txt input output Hadoop会尝试将“words.txt”当作程序名来执行,但示例JAR中并没有这个程序,因此报错。 接下来,我需要验证这种可能性。用户可能在执行命令时将输入文件的名字放在了程序名的位置。正确的做法是确保程序名是示例JAR中存在的,如wordcount、grep等。因此,用户需要检查他们的命令结构是否正确,特别是确保第一个参数是有效的MapReduce程序名,而不是输入文件名。 另外,用户还需要确认输入文件是否已经正确上传到HDFS的指定路径。例如,如果用户打算对words.txt文件进行词频统计,需要先将words.txt上传到HDFS的输入目录(如/input),然后使用正确的命令: hadoop jar examples.jar wordcount /input/words.txt /output 或者,如果输入目录中已经包含words.txt,可以直接指定输入目录为/input。如果用户没有上传文件到HDFS,直接使用本地文件路径,这也会导致错误,因为Hadoop MapReduce作业需要从HDFS读取输入数据。 此外,用户可能混淆了本地文件系统和HDFS路径。Hadoop命令中的路径默认是HDFS路径,除非特别指定为本地文件系统(使用file:///前缀)。因此,用户需要确保输入文件已经通过hdfs dfs -put命令上传到HDFS中,并且在命令中使用HDFS路径。 另一个可能性是用户使用的示例JAR文件中确实不包含所需的程序名。例如,某些Hadoop版本可能示例程序名称不同,或者用户可能错误地拼写了程序名。需要检查hadoop-mapreduce-examples-3.1.3.jar中包含的程序列表,可以使用以下命令列出所有可用的程序: hadoop jar $HADOOP_HOME/share/hadoop/mapreduce/hadoop-mapreduce-examples-3.1.3.jar 运行这个命令而不带参数通常会列出所有可用的示例程序,用户应确认wordcount或其他所需程序是否存在其中。 此外,用户可能遇到了环境变量配置的问题,例如HADOOP_HOME未正确设置,导致无法找到示例JAR文件。需要确保HADOOP_HOME环境变量指向正确的安装目录,并且在命令中使用正确的路径。 还要考虑Hadoop集群的状态是否正常。如果集群未正确启动,或者资源管理器、节点管理器等服务未运行,MapReduce作业可能无法启动,导致其他错误。但根据用户提供的错误信息,更可能的是命令结构的问题,而不是集群状态。 另外,引用[3]中提到的一个错误是找不到主类org.apache.hadoop.mapreduce.v2.app.MRAppMaster,这可能与Hadoop的类路径配置有关,但用户当前的错误是不同的,因此暂时不需要考虑这个方面,除非用户在解决当前问题后遇到其他错误。 总结可能的原因: 1. 命令结构错误,将输入文件名误作为程序名。 2. 输入文件未正确上传到HDFS。 3. 使用了本地文件路径而非HDFS路径。 4. 示例JAR中不存在指定的程序名。 5. 环境变量配置错误导致无法找到JAR文件。 针对这些可能性,我需要逐步指导用户检查命令结构、文件路径、HDFS中的文件存在性以及示例程序的可用性。同时,提供正确的命令示例和操作步骤,确保用户能够正确执行MapReduce作业。</think>### 解决Hadoop命令中“Unknown program 'words.txt'”错误的方法 #### **错误原因分析** 该错误通常是由于**命令结构错误**导致的。Hadoop的`hadoop jar`命令要求第一个参数是**MapReduce示例程序名称**(如`wordcount`),而用户可能误将输入文件名`words.txt`作为程序名传递。例如: ```bash # 错误示例:将words.txt作为程序名 hadoop jar hadoop-mapreduce-examples-3.1.3.jar words.txt /input /output ``` 由于示例JAR中不存在名为`words.txt`的程序,因此会报错`Unknown program`[^1][^2]。 --- #### **解决方法** ##### 步骤1:检查命令结构 确保命令格式为: ```bash hadoop jar <示例JAR路径> <程序名> <输入路径> <输出路径> ``` 例如,使用`wordcount`程序统计词频: ```bash hadoop jar $HADOOP_HOME/share/hadoop/mapreduce/hadoop-mapreduce-examples-3.1.3.jar wordcount /input /output ``` - **程序名**必须是示例JAR支持的类型(如`wordcount`、`grep`等)。 - **输入/输出路径**应为HDFS路径(如`/input`),而非本地文件路径。 ##### 步骤2:验证输入文件已上传到HDFS 1. 将本地文件`words.txt`上传到HDFS: ```bash hdfs dfs -put words.txt /input ``` 2. 检查HDFS中的文件: ```bash hdfs dfs -ls /input ``` ##### 步骤3:确认示例程序名称 通过以下命令查看所有支持的示例程序: ```bash hadoop jar $HADOOP_HOME/share/hadoop/mapreduce/hadoop-mapreduce-examples-3.1.3.jar ``` 输出应包含类似内容: ``` An example program must be given as the first argument. Valid program names are: aggregatewordcount: 统计词频 wordcount: 标准词频统计 ... ``` ##### 步骤4:检查环境变量配置 确保`HADOOP_HOME`已正确设置: ```bash echo $HADOOP_HOME # 应输出Hadoop安装路径,例如/usr/local/hadoop ``` --- #### **完整操作示例** ```bash # 1. 上传文件到HDFS hdfs dfs -mkdir /input hdfs dfs -put words.txt /input # 2. 运行wordcount程序 hadoop jar $HADOOP_HOME/share/hadoop/mapreduce/hadoop-mapreduce-examples-3.1.3.jar wordcount /input /output # 3. 查看结果 hdfs dfs -cat /output/part-r-00000 ``` --- #### **可能关联问题** 1. **如果报错“找不到主类”**(如`MRAppMaster`),需检查`HADOOP_CLASSPATH`是否包含`$HADOOP_HOME/share/hadoop/tools/lib/*`[^3]。 2. 若集群未启动,需先执行: ```bash start-dfs.sh && start-yarn.sh ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值