本文主要讲解三个问题:
1.
我开始使用如下方式进行传递.
在主类中声明两个静态变量, 然后在 main 函数中给变量赋值, 试图在
map和reduce函数中获得变量的值。
代码结构类似如下:
提交到集群运行发现在 map 和 reduce函数中, 静态变量MaxScore的值始终是初值1。
于是试图在主类的静态区中给变量赋值 (因为静态区中的代码比main中的代码要先执行), 仍是不成功,
MaxScore的值始终是初值1。
将上述代码在 单机hadoop上运行, 结果正常, map 函数中能获得变量的值。
思考是这个原因: 在提交作业到hadoop集群后,mapper类和reducer类就到各个 tasktracker上去运行了,
与主类独立, 不能交互。
因此,上述往 map 和 reduce 函数传参数的方法实在太天真。
于是想到其它一些方法: 例如将参数写入hdfs文件中, 然后在 mapper 和 reducer 类的 run方法中读取文件,
并将值读到相应变量,这是可行的,但是方法较复杂,代码如下:
上述方法尽管可用, 但是不是常规方法, 下面介绍常用的方法:
(1) 通过 Configuration 来传递参数
在main函数中调用set方法设置参数, 例如:
在mapper中通过上下文context来获取当前作业的配置, 并获取参数, 例如:
注: context 很有用, 能获取当前作业的大量信息,例如上面就获取了任务ID.
(2)
示例: main中:
这样,Text对象maxscore就以“maxscore”作为key存储在conf对象中了,然后在map和reduce函数中调用load的方法便可以把对象读出。 mapper获取:
(2) 参考自:http://blog.sina.com.cn/s/blog_6b7cf18f0100x9jg.html
2.
可以通过 streaming 的 cmdenv 选项设置环境变量,然后在 map 和 reduce 脚本中获取环境变量。
可参考 << hadoop streaming 高级编程 >> http:///mapreduce/hadoop-streaming-advanced-programming/
(0) 作业提交脚本: #!/usr/bin/env bash max_read_count=${array[0]} min_read_count=${array[1]} max_write_count=${array[2]} min_write_count=${array[3]}
hadoop jar $HADOOP_HOME/contrib/streaming/hadoop-0.20.2-streaming.jar \
(1) Python mapper.py #!/usr/bin/env python import sys import os
min_r_count = float(os.environ.get('min_read_count')) # get environment variables. max_r_count = float(os.environ.get('max_read_count')) min_w_count = float(os.environ.get('min_write_count')) max_w_count = float(os.environ.get('max_write_count'))
(2)Shell mapper.sh
#!/usr/bin/env bash
while read line do
done
echo $min_read_count $max_read_count
(3)C/C++ mapper.c
#include #include int main(int argc, char *argv[], char *env[]) {
}
注意:
3.
(1) streaming 加载本地单个文件
streaming 支持 实例: 作业提交文件 run.sh
mapper.py
注意:在提交作业时使用的是 -file logs/wbscoretest.log
指定需要加载的文件. wbscoretest.log 文件.
(2) streaming
加载本地多个文件
(3) streaming 加载本地目录 (
若加载多个目录,用逗号隔开,-files 使用streaming的 -file 选项不能加载本地目录, 我实验是如此. 我们可以使用 hadoop 的通用选项 -files 来加载本地目录, 加载成功后在mapreduce脚本中可以像访问本地目录一样访问加载的目录. 实际应用中,我们在编写 分词MapReduce作业时需要加载分词词典,就使用该方法.
作业提交脚本:
map 脚本: 读取目录下的文件.
加载多个目录:
注意:多个目录之间用逗号隔开,且不能有空格,否则会出错,这个限制太蛋疼了。
例如:
(4) streaming编程时在mapreduce脚本中读 hdfs 文件 使用 -files 选项, 后面跟需要读的 hdfs 文件路径. 这样在 mapreduce 脚本中就可以直接通过文件名来访问该文件. 作业提交脚本:
map脚本:
如果需要加载大文件, 我们可以将文件先上传到 hdfs 中, 然后在 mapreduce 脚本中读取 hdfs 文件.
(5) streaming编程时在mapreduce脚本中读 hdfs 目录 使用 -files 选项, 后面跟需要读的 hdfs 目录. 这样在 mapreduce 脚本中就可以像访问本地目录一样访问该目录. 作业提交脚本:
map脚本:
|
|