wordcount案例
run.sh
HADOOP_CMD="/usr/local/src/hadoop-2.6.5/bin/hadoop"
STREAM_JAR_PATH="/usr/local/src/hadoop-2.6.5/share/hadoop/tools/lib/hadoop-streaming-2.6.5.jar"
INPUT_FILE_PATH_1="/1.txt"
OUTPUT_PATH="/output"
$HADOOP_CMD fs -rmr -skipTrash $OUTPUT_PATH
# Step 1.
$HADOOP_CMD jar $STREAM_JAR_PATH \
-input $INPUT_FILE_PATH_1 \
-output $OUTPUT_PATH \
-mapper "python map_new.py" \
-reducer "python red_new.py" \
-file ./map_new.py \
-file ./red_new.py
run.sh是一个shell脚本。由于我们用的是Python开发的,因此需要使用hadoop-streaming方式提交作业。
其中,HADOOP_CMD="/usr/local/src/hadoop-1.2.1/bin/hadoop"指的是hadoop命令的路径。
STREAM_JAR_PATH="/usr/local/src/module/hadoop-2.6.5/share/hadoop/tools/lib/hadoop-streaming-2.6.5.jar"指的是hadoop-Streaming的jar包。
INPUT_FILE_PATH_1="./test.data"指的是统计单词个数的源文件。这里是本地文件路径。
OUTPUT_PATH="/output"指的是结果输出路径,这里指的是hdfs路径。
$HADOOP_CMD fs -rmr -skipTrash $OUTPUT_PATH
这里指的是清楚上一次任务的输出结果,避免出现没必要的错误。
map.py
#!/usr/local/bin/python
import sys
import time
import re
for line in sys.stdin:
ss = line.strip().split(' ')
for s in ss:
#time.sleep(100000)
if s.strip() != "":
l = re.findall(r"[^a-zA_Z]*([a-zA-Z]+)[^a-zA-Z]*", s)
if len(l) > 0:
s = l[0]
print "%s\t%s" % (s, 1)
需要注意的是,map和reduce都是从标准输入读数据。
map.py 处理文中单词的输出格式如下:
red.py
map阶段的输出结果,作为red阶段的标准输入。
#!/usr/local/bin/python
import sys
current_word = None
count_pool = []
sum = 0
for line in sys.stdin:
word, val = line.strip().split('\t')
if current_word == None:
current_word = word
if current_word != word:
for count in count_pool:
sum += count
print "%s\t%s" % (current_word, sum)
current_word = word
count_pool = []
sum = 0
count_pool.append(int(val))
for count in count_pool:
sum += count
print "%s\t%s" % (current_word, str(sum))
red.py数据处理的结果
mapreduce实现wordcount
现在,我们使用mapreduce实现单词统计,并查看结果。
执行bash run.sh
查询输出结果 在/output/part-00000中
上面可以看到,单个出现次数统计完成。 之后的博文中,我将会详细介绍hadoop-Streaming的其他参数,尤其是jobconf。谢谢阅读。
streaming
1)Streaming简介
Hadoop的MapReduce和HDFS均采用Java进行实现,默认提供Java编程接口,用户通过这些编程接口,可以定义map、reduce函数等等。
但是如果希望使用其他语言编写map、reduce函数怎么办呢?
Hadoop提供了一个框架Streaming,Streaming的原理是用Java实现一个包装用户程序的MapReduce程序,该程序负责调用hadoop提供的Java编程接口。
2)运行命令
/…/bin/hadoop streaming
-input /…/input
-output /…/output
-mapper “mapper.py”
-reducer “reducer.py”
-file mapper.py
-file reducer.py
-D mapred.job.name =“wordcount”
-D mapred.reduce.tasks = “1”
3)Streaming常用命令
(1)-input
指定作业输入,path可以是文件或者目录,可以使用*通配符,-input选项可以使用多次指定多个文件或目录作为输入。
(2)-output
指定作业输出目录,path必须不存在,而且执行作业的用户必须有创建该目录的权限,-output只能使用一次。
(3)-mapper:
指定mapper可执行程序或Java类,必须指定且唯一。
(4)-reducer:
指定reducer可执行程序或Java类,必须指定且唯一。
(5)-file, -cacheFile, -cacheArchive:
分别用于向计算节点分发本地文件、HDFS文件和HDFS压缩文件,具体使用方法参考文件分发与打包。
(6)numReduceTasks:
指定reducer的个数,如果设置-numReduceTasks 0或者-reducer NONE则没有reducer程序,mapper的输出直接作为整个作业的输出。
(7)-jobconf | -D NAME=VALUE:
指定作业参数,NAME是参数名,VALUE是参数值,可以指定的参数参考hadoop-default.xml。
-jobconf mapred.job.name='My Job Name’设置作业名
-jobconf mapred.job.priority=VERY_HIGH | HIGH | NORMAL | LOW | VERY_LOW设置作业优先级
-jobconf mapred.job.map.capacity=M设置同时最多运行M个map任务
-jobconf mapred.job.reduce.capacity=N设置同时最多运行N个reduce任务
-jobconf mapred.map.tasks 设置map任务个数
-jobconf mapred.reduce.tasks 设置reduce任务个数
-jobconf mapred.compress.map.output 设置map的输出是否压缩
-jobconf mapred.map.output.compression.codec 设置map的输出压缩方式
-jobconf mapred.output.compress 设置reduce的输出是否压缩
-jobconf mapred.output.compression.codec 设置reduce的输出压缩方式
-jobconf stream.map.output.field.separator 设置map输出分隔符
例子:-D stream.map.output.field.separator=: \ 以冒号进行分隔
-D stream.num.map.output.key.fields=2 \ 指定在第二个冒号处进行分隔,也就是第二个冒号之前的作为key,之后的作为value
(8)-combiner:
指定combiner Java类,对应的Java类文件打包成jar文件后用-file分发。
(9)-partitioner:
指定partitioner Java类,Streaming提供了一些实用的partitioner实现,参考KeyBasedFiledPartitoner和IntHashPartitioner。
(10)-inputformat, -outputformat:
指定inputformat和outputformat Java类,用于读取输入数据和写入输出数据,分别要实现InputFormat和OutputFormat接口。如果不指定,默认使用TextInputFormat和TextOutputFormat。
(11)cmdenv NAME=VALUE:
给mapper和reducer程序传递额外的环境变量,NAME是变量名,VALUE是变量值。
(12)-mapdebug, -reducedebug:
分别指定mapper和reducer程序失败时运行的debug程序。
(13)-verbose:
指定输出详细信息,例如分发哪些文件,实际作业配置参数值等,可以用于调试。