Hadoop Streaming

来源:互联网 发布:淘宝tbi数据包怎么用 编辑:程序博客网 时间:2024/05/18 03:51

Hadoop Streaming 是Hadoop提供的一个编程工具,Streamining框架允许任何可执行文件或者脚本文件作为Mapper和Reducer在Hadoop MapReduce中使用,方便已有程序向Hadoop平台移植。因此可以说对于hadoop的扩展性意义重大。

Streamining的原理:mapper和reducer会从标准输入中读取数据,一行一行处理后发送给标准输出,Streming 工具会创建MapReduce作业,发送给各个tasktracker,同时监控整个作业的执行过程。

如果一个文件(可执行文件或脚本)作为mapper,mapper初始化时,每一个mapper任务会把该文件作为一个单独进程启动,mapper任务运行时,它把输入切分成行并把每一行提供给可执行文件进程的标准输入,同时,mapper收集可执行文件进程标准输出的内容,并把收到的每一行内容转化成key/value对,作为mapper的输出,默认情况下,一行中第一个tab之前的部分作为key,之后的作为value。如果没有tab,整行作为key,value值为null。

具体参数调优可以参考 http://www.uml.org.cn/zjjs/201205303.asp

基本用法

HADOOPHOME/bin/hadoopjar HADOOP_HOME/share/hadoop/tools/lib/hadoop-streaming-2.7.3.jar [options]

options:

 - -input: 输入文件路径 - -output:输出文件路径 - -mapper: 用户自己写的mapper程序,可以是可执行文件或脚本 -  -reducer: 用户自己写的reducer程序,可以是可执行文件或脚本 - -file:打包文件到提交的作业中,可以是mapper或者reducer要用的输入文件,如配置文件、字典等 - -partitioner:用户自定义的partitioner程序 - -combiner:用户自定义的combiner程序 - -D:作业的一些属性(以前用的是-joncof)

例1:

${BIN_HADOOP} fs -rm -r "${OUTPUT}"${BIN_HADOOP} jar "${jarPack}" \    -input "${INPUT}/part*" \    -output "${OUTPUT}" \    -mapper "${PYTHON_BIN}  map.py" \    -reducer "${PYTHON_BIN} reduce.py" \    -jobconf mapred.job.name="*****" \    -jobconf mapred.job.priority=VERY_HIGH \    -jobconf mapred.job.map.capacity=200 \    -jobconf mapred.job.reduce.capacity=200 \    -jobconf mapred.reduce.tasks=200 \    -jobconf mapred.min.split.size=20480000000 \    -jobconf mapred.map.memory.limit=2000 \    -jobconf mapred.map.over.capacity.allowed=true \    -cacheArchive "${PYTHON_PACK}#taskenv" \    -file map.py \    -file init.conf
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

上面例子上传了当前环境的python包(就是将当前环境python环境下的bin include lib share压缩tar),然后上传到HDFS(PYTHON_PACK),启动Streamining时,使用-cacheArchive选项将其分发到计算结点并解压到taskenv目录,PYTHON_BIN=”taskenv/python27/bin/python”,本地打包时要进入目录app而不是在app的上层目录打包,否则要通过app/app/mapper.pl才能访问到mapper.pl文件。

例2:

${BIN_HADOOP} fs -rm -r "${OUTPUT}"${BIN_HADOOP} jar "${jarPack}" \    -D mapreduce.map.memory.mb=2800 \    -D mapred.map.tasks=400 \    -D stream.non.zero.exit.is.failure=false \    -file map.py \    -input "${INPUT}" \    -output "${OUTPUT}" \    -mapper map.py \    -jobconf mapred.map.over.capacity.allowed=true \    -cacheFile "${PYTHON_FILE}#tasklink" \    -jobconf mapred.job.map.capacity=20 \    -jobconf mapreduce.job.name="****"
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

上例上传了一个文件,其中在map.py可以通过(“./tasklink”)直接访问${PYTHON_FILE}文件。

Streamining不足

  • Hadoop Streamining 默认只能处理文本数据,无法直接处理二进制数据进行处理
  • Streaming中的mapper和reducer默认只能标准输出写数据,不能方便的处理多路输出

基础配置参数介绍

下面参数中-files,-archives,-libjars为hadoop命令

  • -file将客户端本地文件打成jar包上传到HDFS然后分发到计算节点
  • -cacheFile将HDFS文件分发到计算节点
  • -cacheArchive将HDFS压缩文件分发到计算节点并解压,也可以指定符号链接
  • -files:将指定的本地/hdfs文件分发到各个Task的工作目录下,不对文件进行任何处理,例如:-files hdfs://host:fs_port/user/testfile.txt#testlink ;
  • -archives选项允许用户复制jar包到当前任务的工作路径,并且自动解压jar包,例如:-archives hdfs://host:fs_port/user/testfile.jar#testlink3 。在这个例子中,符号链接testlink3创建在当前任务的工作路径中。符号链接指向存放解压jar包的文件路径
  • -libjars:指定待分发的jar包,Hadoop将这些jar包分发到各个节点上后,会将其自动添加到任务的CLASSPATH环境变量中
  • -input:指定作业输入,可以是文件或者目录,可以使用*通配符,也可以使用多次指定多个文件或者目录作为输入
  • -output:指定作业输出目录,并且必须不存在,并且必须有创建该目录的权限,-output只能使用一次
  • -mapper:指定mapper可执行程序或Java类,必须指定且唯一
  • -reducer:指定reducer可执行程序或Java类
  • -numReduceTasks: 指定reducer的个数,如果设置为0或者-reducer NONE 则没有reducer程序,mapper的输出直接作为整个作业的输出

其他参数配置

一般用 -jobconf | -D NAME=VALUE 指定作业参数,指定 mapper or reducer 的 task 官方上说要用 -jobconf 但是这个参数已经过时,不可以用了,官方说要用 -D, 注意这个-D是要作为最开始的配置出现的,因为是在maper 和 reducer 执行之前,就需要硬性指定好的,所以要出现在参数的最前面 ./bin/hadoop jar hadoop-0.19.2-streaming.jar -D ………-input …….. 类似这样

  • mapred.job.name=”jobname” 设置作业名,特别建议
  • mapred.job.priority=VERY_HIGH|HIGH|NORMAL|LOW|VERY_LOW 设置作业优先级
  • * mapred.job.map.capacity=M设置同时最多运行M个map任务*
  • mapred.job.reduce.capacity=N 设置同时最多运行N个reduce任务
  • mapred.map.tasks 设置map任务个数
  • mapred.reduce.tasks 设置reduce任务个数
  • mapred.job.groups 作业可运行的计算节点分组
  • mapred.task.timeout 任务没有响应(输入输出)的最大时间
  • mapred.compress.map.output 设置map的输出是否压缩
  • mapred.map.output.compression.codec 设置map的输出压缩方式
  • mapred.output.compress 设置map的输出是否压缩
  • mapred.output.compression.codec 设置reduce的输出压缩方式
  • stream.map.output.field.separator 指定map输出分隔符,默认情况下Streaming框架将map输出的每一行的第一个’\t’之前的部分作为key,之后的部分作为value,key\value再作为reduce的输入;
  • stream.num.map.output.key.fields 设置分隔符的位置,如果设置为2,指定在第2个分隔符处分割,也就是第二个之前作为key,之后作为value,如果分隔符少于2个,则以整行为key,value为空
  • stream.reduce.output.field.separator 指定reduce输出分隔符
  • stream.num.reduce.output.key.fields 指定reduce输出分隔符位置

其中sort和partition的参数用的比较多 
map.output.key.field.separator: map中key内部的分隔符 
num.key.fields.for.partition: 分桶时,key按前面指定的分隔符分隔之后,用于分桶的key占的列数。通俗地讲,就是partition时候按照key中的前几列进行划分,相同的key会被打到同一个reduce里。 
-partitioner org.apache.hadoop.mapred.lib.KeyFieldBasedPartitioner 前两个参数,要配合partitioner选项使用!

stream.map.output.field.separator: map中的key与value分隔符 
stream.num.map.output.key.fields: map中分隔符的位置 
stream.reduce.output.field.separator: reduce中key与value的分隔符 
stream.num.reduce.output.key.fields: reduce中分隔符的位置

另外还有压缩参数

Job输出结果是否压缩

mapred.output.compress

是否压缩,默认值false。

mapred.output.compression.type

压缩类型,有NONE, RECORD和BLOCK,默认值RECORD。

mapred.output.compression.codec

压缩算法,默认值org.apache.hadoop.io.compress.DefaultCodec。

map task输出是否压缩

mapred.compress.map.output

是否压缩,默认值false

mapred.map.output.compression.codec

压缩算法,默认值org.apache.hadoop.io.compress.DefaultCodec

另外,Hadoop本身还自带一些好用的Mapper和Reducer:

1、Hadoop聚集功能:Aggregate提供一个特殊的reducer类和一个特殊的combiner类,并且有一系列的“聚合器”(例如:sum、max、min等)用于聚合一组value的序列。可以使用Aggredate定义一个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。


二次排序 Partitioner

一个典型的Map-Reduce的过程包括:Input->Map->Patition->Reduce->Output,Partition负责把Map任务输出的中间结果按key分发给不同的Reduce任务进行处理。Hadoop提供了一个非常实用的partitioner类KeyFieldBasedPartitioner,使用方法:

-partitioner org.apache.hadoop.mapred.lib.KeyFieldBasedPartitioner 
  • 1

一般会配合

-D map.output.key.field.separator  ###key内部的分隔符-D num.key.fields.for.partition    ###对key分出来的前即部分做parititon,而不是整个key
  • 1
  • 2

使用,但是map.output.key.field.separator对tab键好像不管用,待验证

例3:

测试数据: 
1,2,1,1,1

1,2,2,1,1

1,3,1,1,1

1,3,2,1,1

1,3,3,1,1

1,2,3,1,1

1,3,1,1,1

1,3,2,1,1

1,3,3,1,1

-D stream.map.output.field.separator=, /    -D stream.num.map.output.key.fields=4 /    -D map.output.key.field.separator=, /    -D num.key.fields.for.partition=2 /    -partitioner org.apache.hadoop.mapred.lib.KeyFieldBasedPartitioner /
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

结果数据: 
$ hadoop fs –cat /app/test/test_result/part-00003

1,2,1,1 1

1,2,2,1 1

1,2,3,1 1

$ hadoop fs –cat /app/test/test_result/part-00004

1,3,1,1 1

1,3,1,1 1

1,3,2,1 1

1,3,2,1 1

1,3,3,1 1

1,3,3,1 1

例4

测试数据: 
D&10.2.3.40 1 
D&11.22.33.33 1 
W&www.renren.com 1 
W&www.baidu.com 1 
D&10.2.3.40 1 
然后通过传递命令参数 
-partitioner org.apache.hadoop.mapred.lib.KeyFieldBasedPartitioner //指定要求二次排序 
-jobconf map.output.key.field.separator=’&’ //这里如果不加两个单引号的话我的命令会死掉 
-jobconf num.key.fields.for.partition=1 //这里指第一个 & 符号来分割,保证不会出错

-combiner?? 
Comparator类

原创粉丝点击