- 浏览: 155131 次
- 性别:
- 来自: 北京
文章分类
- 全部博客 (113)
- Java工具类 (3)
- Hibernate (1)
- Struts>1&2 (0)
- Spring (0)
- Web前端 (1)
- 数据库 (2)
- 中间件 (3)
- 搜索引擎 (11)
- EJB (1)
- Log日志 (1)
- OS操作系统 (7)
- Java文档 (4)
- Security (1)
- Exception&Error (7)
- 日志&心情 (7)
- 开心一下 (3)
- 云计算 (41)
- Cache缓存 (4)
- MongoDB (1)
- OS操作系统 Linux (7)
- jquery (1)
- 机器学习 (2)
- Plugins (2)
- AJAX (1)
- Java工具 (1)
- WebService (1)
最新评论
-
a420144030:
你好,我想计算n篇文章的相似度,用mahout能处理吗,如何做 ...
mahout使用 -
di1984HIT:
OK,真的很牛啊
hadoop常见错误 -
xwl1991:
还真是这个问题 !
quartz报错java.lang.NoSuchMethodError: org.apache.commons.collections.SetUtils.ord
1、概述
Hadoop Streaming是Hadoop提供的一个编程工具,它允许用户使用任何可执行文件或者脚本文件作为Mapper和Reducer,例如:
采用shell脚本语言中的一些命令作为mapper和reducer(cat作为mapper,wc作为reducer)
$HADOOP_HOME/bin/hadoop jar $HADOOP_HOME/hadoop-streaming.jar \
-input myInputDirs \
-output myOutputDir \
-mapper cat \
-reducer wc
本文安排如下,第二节介绍Hadoop Streaming的原理,第三节介绍Hadoop Streaming的使用方法,第四节介绍Hadoop Streaming的程序编写方法,在这一节中,用C++、C、shell脚本 和python实现了WordCount作业,第五节总结了常见的问题。文章最后给出了程序下载地址 。(本文内容基于Hadoop-0.20.2版本 )
(注:如果你采用的语言为C或者C++,也可以使用Hadoop Pipes,具体可参考这篇文章:Hadoop Pipes编程。 )
关于Hadoop Streaming高级编程方法,可参考这篇文章:Hadoop Streaming高级编程 。
2、Hadoop Streaming原理
mapper和reducer会从标准输入中读取用户数据,一行一行处理后发送给标准输出。Streaming工具会创建MapReduce作业,发送给各个tasktracker,同时监控整个作业的执行过程。
如果一个文件(可执行或者脚本)作为mapper,mapper初始化时,每一个mapper任务会把该文件作为一个单独进程启动,mapper任 务运行时,它把输入切分成行并把每一行提供给可执行文件进程的标准输入。 同时,mapper收集可执行文件进程标准输出的内容,并把收到的每一行内容转化成key/value对,作为mapper的输出。 默认情况下,一行中第一个tab之前的部分作为key ,之后的(不包括tab)作为value 。 如果没有tab,整行作为key值,value值为null。
对于reducer,类似。
以上是Map/Reduce框架和streaming mapper/reducer之间的基本通信协议。
3、Hadoop Streaming用法
Usage: $HADOOP_HOME/bin/hadoop jar \
$HADOOP_HOME/hadoop-streaming.jar [options]
options:
(1)-input:输入文件路径
(2)-output:输出文件路径
(3)-mapper:用户自己写的mapper程序,可以是可执行文件或者脚本
(4)-reducer:用户自己写的reducer程序,可以是可执行文件或者脚本
(5)-file:打包文件到提交的作业中,可以是mapper或者reducer要用的输入文件,如配置文件,字典等。
(6)-partitioner:用户自定义的partitioner程序
(7)-combiner:用户自定义的combiner程序(必须用java实现)
(8)-D:作业的一些属性(以前用的是-jonconf),具体有:
1)mapred.map.tasks:map task数目
2)mapred.reduce.tasks:reduce task数目
3)stream.map.input.field.separator/stream.map.output.field.separator: map task输入/输出数
据的分隔符,默认均为\t。
4)stream.num.map.output.key.fields:指定map task输出记录中key所占的域数目
5)stream.reduce.input.field.separator/stream.reduce.output.field.separator:reduce task输入/输出数据的分隔符,默认均为\t。
6)stream.num.reduce.output.key.fields:指定reduce task输出记录中key所占的域数目
另外,Hadoop本身还自带一些好用的Mapper和Reducer:
(1) Hadoop聚集功能
Aggregate提供一个特殊的reducer类和一个特殊的combiner类,并且有一系列的“聚合器”(例如 “sum”,“max”,“min”等)用于聚合一组value的序列。用户可以使用Aggregate定义一个mapper插件类,这个类用于为 mapper输入的每个key/value对产生“可聚合项”。Combiner/reducer利用适当的聚合器聚合这些可聚合项。要使用 Aggregate,只需指定“-reducer aggregate”。
(2)字段的选取(类似于Unix中的‘cut’)
Hadoop的工具类org.apache.hadoop.mapred.lib.FieldSelectionMapReduc帮助用户高效处理 文本数据,就像unix中的“cut”工具。工具类中的map函数把输入的key/value对看作字段的列表。 用户可以指定字段的分隔符(默认是tab),可以选择字段列表中任意一段(由列表中一个或多个字段组成)作为map输出的key或者value。 同样,工具类中的reduce函数也把输入的key/value对看作字段的列表,用户可以选取任意一段作为reduce输出的key或value。
4、Mapper和Reducer实现
本节试图用尽可能多的语言编写Mapper和Reducer,包括Java,C,C++,Shell脚本,python等。
由于Hadoop会自动解析数据文件到Mapper或者Reducer的标准输入中,以供它们读取使用,所有应先了解各个语言获取标准输入的方法。
(1) Java语言:
见Hadoop自带例子
(2) C++语言 :
1
2
3
4
|
string key;
while
(cin>>key){
cin>>value;
….
|
(3) C语言 :
1
2
3
4
5
|
char
buffer[BUF_SIZE];
while
(
fgets
(buffer, BUF_SIZE - 1, stdin)){
int
len =
strlen
(buffer);
…
}
|
(4) Shell脚本
用管道
(5) Python脚本
1
2
3
|
import
sys
for
line
in
sys.stdin:
.......
|
为了说明各种语言编写Hadoop Streaming程序的方法,下面以WordCount为例,WordCount作业的主要功能是对用户输入的数据中所有字符串进行计数。
(1)C语言实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
|
//mapper
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define BUF_SIZE 2048
#define DELIM "\n"
int
main(
int
argc,
char
*argv[]){
char
buffer[BUF_SIZE];
while
(
fgets
(buffer, BUF_SIZE - 1, stdin)){
int
len =
strlen
(buffer);
if
(buffer[len-1] ==
'\n'
)
buffer[len-1] = 0;
char
*querys = index(buffer,
' '
);
char
*query = NULL;
if
(querys == NULL)
continue
;
querys += 1;
/* not to include '\t' */
query =
strtok
(buffer,
" "
);
while
(query){
printf
(
"%s\t1\n"
, query);
query =
strtok
(NULL,
" "
);
}
}
return
0;
}
//---------------------------------------------------------------------------------------
//reducer
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define BUFFER_SIZE 1024
#define DELIM "\t"
int
main(
int
argc,
char
*argv[]){
char
strLastKey[BUFFER_SIZE];
char
strLine[BUFFER_SIZE];
int
count = 0;
*strLastKey =
'\0'
;
*strLine =
'\0'
;
while
(
fgets
(strLine, BUFFER_SIZE - 1, stdin) ){
char
*strCurrKey = NULL;
char
*strCurrNum = NULL;
strCurrKey =
strtok
(strLine, DELIM);
strCurrNum =
strtok
(NULL, DELIM);
/* necessary to check error but.... */
if
( strLastKey[0] ==
'\0'
){
strcpy
(strLastKey, strCurrKey);
}
if
(
strcmp
(strCurrKey, strLastKey)){
printf
(
"%s\t%d\n"
, strLastKey, count);
count =
atoi
(strCurrNum);
}
else
{
count +=
atoi
(strCurrNum);
}
strcpy
(strLastKey, strCurrKey);
}
printf
(
"%s\t%d\n"
, strLastKey, count);
/* flush the count */
return
0;
}
|
(2)C++语言实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
|
//mapper
#include <stdio.h>
#include <string>
#include <iostream>
using
namespace
std;
int
main(){
string key;
string value =
"1"
;
while
(cin>>key){
cout<<key<<
"\t"
<<value<<endl;
}
return
0;
}
//------------------------------------------------------------------------------------------------------------
//reducer
#include <string>
#include <map>
#include <iostream>
#include <iterator>
using
namespace
std;
int
main(){
string key;
string value;
map<string,
int
> word2count;
map<string,
int
>::iterator it;
while
(cin>>key){
cin>>value;
it = word2count.find(key);
if
(it != word2count.end()){
(it->second)++;
}
else
{
word2count.insert(make_pair(key, 1));
}
}
for
(it = word2count.begin(); it != word2count.end(); ++it){
cout<<it->first<<
"\t"
<<it->second<<endl;
}
return
0;
}
|
(3)shell脚本语言实现
1
2
3
4
5
|
$HADOOP_HOME
/bin/hadoop
jar $HADOOP_HOME
/hadoop-streaming
.jar \
-input myInputDirs \
-output myOutputDir \
-mapper
cat
\
-reducer
wc
|
(4)Python脚本语言实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
|
#!/usr/bin/env python
import
sys
# maps words to their counts
word2count
=
{}
# input comes from STDIN (standard input)
for
line
in
sys.stdin:
# remove leading and trailing whitespace
line
=
line.strip()
# split the line into words while removing any empty strings
words
=
filter
(
lambda
word: word, line.split())
# increase counters
for
word
in
words:
# write the results to STDOUT (standard output);
# what we output here will be the input for the
# Reduce step, i.e. the input for reducer.py
#
# tab-delimited; the trivial word count is 1
print
'%s\t%s'
%
(word,
1
)
#---------------------------------------------------------------------------------------------------------
#!/usr/bin/env python
from
operator
import
itemgetter
import
sys
# maps words to their counts
word2count
=
{}
# input comes from STDIN
for
line
in
sys.stdin:
# remove leading and trailing whitespace
line
=
line.strip()
# parse the input we got from mapper.py
word, count
=
line.split()
# convert count (currently a string) to int
try
:
count
=
int
(count)
word2count[word]
=
word2count.get(word,
0
)
+
count
except
ValueError:
# count was not a number, so silently
# ignore/discard this line
pass
# sort the words lexigraphically;
#
# this step is NOT required, we just do it so that our
# final output will look more like the official Hadoop
# word count examples
sorted_word2count
=
sorted
(word2count.items(), key
=
itemgetter(
0
))
# write the results to STDOUT (standard output)
for
word, count
in
sorted_word2count:
print
'%s\t%s'
%
(word, count)
|
5、常见问题
(1)作业总是运行失败:
需要把mapper文件和reducer文件放到各个tasktracker上,保证各个节点均有一份。也可在提交作业时,采用-file选项指定这些文件。
(2)用脚本编写时,第一行需注明脚本解释器,默认是shell
6、参考资料
【1】C++&Python实现Hadoop Streaming的paritioner和模块化
【2】如何在Hadoop中使用Streaming编写MapReduce
7、程序打包下载
文章中用到的程序源代码可在此处下载 !
转载自董的博客
本文链接地址: http://dongxicheng.org/mapreduce/hadoop-streaming-programming/
发表评论
-
用Sqoop把数据从HDFS导入到MYSQL
2012-10-27 23:30 2354转自:http://www.kaifajie.cn/mySQL ... -
大数据的储存:百度HDFS集群的数据压缩
2012-08-30 17:48 12072012年4月13日,由IT168(ITP ... -
用sqoop进行mysql和hdfs系统间的数据互导
2012-07-31 16:32 1942转自:http://abloz.com/2012/07/19/ ... -
从hive将数据导出到mysql
2012-07-31 16:31 1825转自:http://abloz.com/2012/07/20/ ... -
Hive SQL
2012-07-19 13:49 1427转自:http://www.tbdata.org/ ... -
Hive优化总结
2012-07-09 15:18 4333优化时,把hive sql当做ma ... -
hadoop/mapred 优化方法
2012-06-12 11:47 1397从三个方面着手优化 : 1. hadoop配置 2. ... -
hadoop集群dfs.data.dir目录权限问题导致节点无法启动
2012-06-11 18:32 6228安装使用Hive的时候发现文件无法从本地拷贝到hadoo ... -
hadoop中的balancer
2012-06-11 15:49 1145对于HDFS集群,经常长时间的运行,尤其是大量的delete操 ... -
Hadoop集群上使用Lzo压缩
2012-05-28 11:03 935转自:http://www.tech126.com/hadoo ... -
使用Hive读取Hbase中的数据
2012-05-23 13:12 2274转自:http://www.4ucode.com/Study/ ... -
在XP系统下配置eclipse集成hadoop开发
2012-05-05 11:09 1048一、目的:由于hadoop只能在Linux环境下运行,所以对于 ... -
使用Hive读取Hbase中的数据
2012-04-18 14:24 1098转自:http://www.4ucode.com/Study/ ... -
Web日志分析方法概述 让复杂的数据挖掘变得简单可行
2012-04-13 16:31 874志在计算机系统中是一个非常广泛的概念,任何程序都有可能输出日志 ... -
应用sqoop将MySQL数据库中的数据导入Hbase
2012-04-12 11:31 2066转自:http://www.bwxxkj.com/a/jish ... -
hadoop中的trash机制,恢复删除的文件
2012-03-31 13:46 2201Hadoop回收站trash,默认是关闭的。 1.修改con ... -
Hadoop 和DBMS 的互补性
2012-03-29 12:22 673随着Microsoft 也加入Hadoop 阵营,Hadoop ... -
Hadoop 中的两表join
2012-03-29 12:20 851转自:http://www.gemini52013 ... -
各版本编译hadoop eclipse plugin
2012-03-29 12:19 1384转自:http://www.gemini52013 ... -
hadoop常见错误
2012-03-24 13:04 1667错误1:bin/hadoop dfs 不能正常启动,持续提 ...
相关推荐
【Hadoop Streaming编程详解】 Hadoop Streaming是一种编程接口,它允许开发者使用任意可执行文件或脚本(如Shell、Python、Perl等)作为MapReduce作业的Mapper和Reducer。这一技术极大地扩展了Hadoop的适用性,...
Hadoop Streaming是一个非常有用的工具,它能够使得任何用编程语言实现的程序能够在Hadoop MapReduce框架中运行。Hadoop Streaming利用标准输入和标准输出来实现程序与MapReduce框架之间的通信。这个特性使得已经...
Hadoop Streaming是Hadoop生态系统中的一个组件,它允许用户使用自定义的编程语言(如Python、Perl或Ruby)编写MapReduce程序,而不仅仅是Java。这一特性极大地扩展了Hadoop的适用范围,使得不同背景的开发者都能够...
4. **HadoopStreaming.class**: 这个类是 Hadoop Streaming 的核心,它实现了 MapReduce 框架,使得用户可以使用非Java语言编写 Map 和 Reduce 部分。 Hadoop Streaming 的标签 "jar 2.8.0 hadoop streaming" 强调...
通过以上详细说明,可以看出 Hadoop Streaming 提供了一种灵活的方式来处理大数据,并允许使用多种编程语言和工具。这对于那些不熟悉 Java 或希望使用特定领域语言解决问题的开发者来说尤其有用。
### Hadoop Streaming 知识点详解 #### 一、Hadoop及Hadoop Streaming简介 **Hadoop** 是一个能够对大量数据进行分布式处理的软件框架,由Apache基金会维护。它支持大规模的数据集(TB级别及以上),并通过...
Hadoop为MapReduce提供了不同的API,可以方便我们使用不同的编程语言来使用MapReduce框架,而不是只局限于Java。这里要介绍的就是Hadoop streaming API。Hadoop streaming 使用Unix的standard streams作为我们...
Hadoop Streaming是Hadoop的MapReduce编程模型的一个工具,它允许用户使用非Java语言编写MapReduce作业,使得其他编程语言如Python、Ruby和Perl等能够处理Hadoop上的大数据。Hadoop Streaming通过将数据流式传输到...
这个压缩包“使用hadoop-streaming运行Python编写的MapReduce程序.rar”显然是一个教程或示例,旨在指导用户如何利用Python编写MapReduce任务,并通过Hadoop Streaming进行执行。 MapReduce是一种编程模型,由...
Google为自己的业务需要提出了编程模型MapReduce和分布式文件系统Google File System,并发布了相关论文(可在Google Research的网站上获得: GFS 、 MapReduce)。 Doug Cutting和Mike Cafarella在开发搜索引擎...
在编程时,将这些JAR包导入工程中是确保Hadoop程序正确运行的关键步骤。 首先,我们来了解Hadoop的主要组件和它们对应的JAR包: 1. **Hadoop Common**:这是Hadoop的基础模块,提供了各种通用工具和服务,包括文件...
7. **编程接口**:Hadoop提供了Java API来编写MapReduce程序,但也有如Hadoop Streaming这样的接口,允许使用其他语言(如Python、Perl)编写Mapper和Reducer。 8. **数据处理范式**:MapReduce遵循“批处理”处理...
2. 实时流处理:可能涉及到使用Hadoop的实时处理框架,如Apache Storm或Spark Streaming,处理实时数据流。 3. 大数据应用:比如构建推荐系统、日志分析、社交网络分析等实际场景的应用。 4. 故障恢复和容错机制:...
- 开发者通常使用Java进行Hadoop编程,但也有基于Hadoop的其他编程接口,如Hadoop Streaming允许使用任何可执行的脚本语言(如Python、Perl)。 - Maven或Gradle等构建工具可以帮助管理Hadoop项目的依赖关系,方便...
HDFS放宽了(relax)POSIX的要求(requirements)这样可以流的形式访问(streaming access)文件系统中的数据。 Hadoop的名字不是一个缩写,它是一个虚构的名字。该项目的创建者,Doug Cutting解释Hadoop的得名:...
此外,还有如Hadoop Streaming这样的接口,允许使用其他语言(如Python或Perl)编写MapReduce任务。 七、Hadoop案例分析 教程中可能会包含一些实际案例,如Web日志分析、推荐系统、社交网络分析等,通过这些案例,...