hadoop streaming (shell执行 & combiner & 数据分割)
来源:互联网 发布:如何自学软件编程 编辑:程序博客网 时间:2024/06/05 00:29
1,前言 --- 先上干货:hadoop.streaming 的一个完整的shell脚本;hadoop streaming (shell执行脚本实例 & combiner初探 & 数据分割)
### 2--- tasks
22 HADOOP=/usr/bin/hadoop
23
24 local_file="./wc.data"
25 #input="yapeng/WC/input/*.txt"
26 input="yapeng/WC/input2"
27 output="yapeng/WC/output"
28
29 $HADOOP fs -rm -r -skipTrash $input
30 $HADOOP fs -put $local_file $input
31 $HADOOP fs -rm -r -skipTrash $output
32 #-inputformat com.hadoop.mapred.DeprecatedLzoTextInputFormat \
33 #-D stream.map.input.ignoreKey='true' \
34 $HADOOP org.apache.hadoop.streaming.HadoopStreaming \
35 -D mapred.job.name="WC_TEST" \
36 -D mapred.reduce.tasks=4 \
37 -D mapred.output.compress=true \
38 -D mapred.output.compression.type=BLOCK \
39 -D mapred.output.compression.codec=com.hadoop.compression.lzo.LzopCodec \
40 -input $input \
41 -output $output \
42 -file ./interval.json \
43 -file ./2016112917_badmid.data \
44 -mapper "python wc_mapper.py ./2016112917_badmid.data" -file ./wc_mapper.py \
45 -combiner "python wc_reducer.py" -file ./wc_reducer.py \
46 -reducer "python wc_reducer.py" -file ./wc_reducer.py
47
48 exit -1
49 ### 3--- judge
50 $HADOOP fs -test -e "$OUTPUT/_SUCCESS"
51 if [ $? -eq 0 ]; then
52 echo "Succ!!!"
53 else
54 echo "hadoop task fail!"
55 fi
56
57 ### 4--- cp from remote to local
58 $HADOOP fs -cat "$OUTPUT/part-*" |lzop -dc > wap_wuid_keywordtag.${DAY}
2.1 为什么需要进行Map规约操作
众所周知,Hadoop框架使用Mapper将数据处理成一个个的<key,value>键值对,在网络节点间对其进行整理(shuffle),然后使用Reducer处理数据并进行最终输出。
在上述过程中,我们看到至少两个 性能瓶颈 :
(1)如果我们有10亿个数据,Mapper会生成10亿个键值对在网络间进行传输,但如果我们只是对数据求最大值,那么很明显的Mapper只需要输出它所知道的最大值即可。这样做不仅可以减轻网络压力,同样也可以大幅度提高程序效率。
总结: 网络带宽严重被占降低程序效率;
(2)假设使用美国专利数据集中的国家一项来阐述 数据倾斜 这 个定义,这样的数据远远不是一致性的或者说平衡分布的,由于大多数专利的国家都属于美国,这样不仅Mapper中的键值对、中间阶段(shuffle)的 键值对等,大多数的键值对最终会聚集于一个单一的Reducer之上,压倒这个Reducer,从而大大降低程序的性能。
总结: 单一节点承载过重降低程序性能;那么,有木有一种方案能够解决这两个问题呢?
在MapReduce编程模型中,在Mapper和Reducer之间有一个非常重要的组件,它解决了上述的性能瓶颈问题,它就是 Combiner 。
PS:
①与mapper和reducer不同的是,combiner没有默认的实现,需要显式的设置在conf中才有作用。
②并不是所有的job都适用combiner,只有操作满足结合律的才可设置combiner。combine操作类似于:opt(opt(1, 2, 3), opt(4, 5, 6))。如果opt为求和、求最大值的话,可以使用,但是如果是求中值的话,不适用。
每一个map都可能会产生大量的 本地输出 , Combiner 的作用就是对map端的输出 先做一次合并 ,以 减少在map和reduce节点之间的数据传输量 ,以 提高网络IO性能 ,是MapReduce的一种 优化手段之一
(1)Combiner最基本是实现 本地key的聚合,对map输出的key排序,value进行迭代 。如下所示:
map: (K1, V1) → list(K2, V2)
combine: (K2, list(V2)) → list(K2, V2)
reduce: (K2, list(V2)) → list(K3, V3)
(2)Combiner还有 本地reduce 功能(其本质上就是一个reduce,当然也可以完全独立的一个.py文件),例如Hadoop自带的wordcount的例子和找出value的最大值的程序,combiner和reduce完全一致,如下所示:
map: (K1, V1) → list(K2, V2)
combine: (K2, list(V2)) → list(K3, V3)
reduce: (K3, list(V3)) → list(K4, V4)
PS: 现在想想,如果在wordcount中不用combiner,那么所有的结果都是 reduce完成,效率会相对低下。使用combiner之后,先完成的map会在本地聚合,提升速度。对于hadoop自带的wordcount的例 子,value就是一个叠加的数字,所以map一结束就可以进行reduce的value叠加,而不必要等到所有的map结束再去进行reduce的 value叠加。
3 --- hadoop streaming 的跨语言2),c/cpp需要事先编译成可执行文件,-file的是-o文件,其它的例如run_hadoop.sh 的写法完全和python一致
3),cat wc.data | ./mapper | sort | ./reducer
4), 总之,hadoopstreaming 存在一致性, 核心是根据需求 如何书写map&red的实现,以及选择何种语言的问题
5), 例子:mapper 是c程序, reducer是python。。
##time cat mid_2_vec.all | ./cc hotword_top_kw.vec | sort | python hw_mids_reducer.py
mapred.reduce.slowstart.completed.maps (map完成多少百分比时,开始shuffle)
当map运行慢,reduce运行很快时,如果不设置mapred.reduce.slowstart.completed.maps会使job的shuffle时间变的很长,
map运行完很早就开始了reduce,导致reduce的slot一直处于被占用状态。mapred.reduce.slowstart.completed.maps 这个值是
和“运行完的map数除以总map数”做判断的,当后者大于等于设定的值时,开始reduce的shuffle。所以当map比reduce的执行
时间多很多时,可以调整这个值(0.75,0.80,0.85及以上)
mapred.min.split.size
这个配置决定了每个Input Split 的最小值,也间接决定了一个job的map数量
HDFS块大小是在job写入时决定的,而分片的大小,是由三个元素决定的(在3各种去最大的那个)
(1) 输入的块数 (2) Mapred.min.split.size (3) Job.setNumMapTasks()
mapred.compress.map.output
压缩Map的输出,这样做有两个好处:
a)压缩是在内存中进行,所以写入map本地磁盘的数据就会变小,大大减少了本地IO次数
b) Reduce从每个map节点copy数据,也会明显降低网络传输的时间
注:数据序列化其实效果会更好,无论是磁盘IO还是数据大小,都会明显的降低。
-D stream.map.input.ignoreKey='true' \
-D mapred.job.istunneljob=true \
-D mapred.job.name=$JOBNAME \
-D mapred.reduce.tasks=$REDUCENUM \
-D mapred.output.compress=true \
-D mapred.output.compression.type=BLOCK \
-D mapred.output.compression.codec=com.hadoop.compression.lzo.LzopCodec \
-inputformat com.hadoop.mapred.DeprecatedLzoTextInputFormat \
Hadoop Streaming框架使用(三)
前两篇文章介绍了Hadoop Streaming框架的使用方法。由于篇幅所限,并没有介绍其中的高级使用方法,但是有一些用法还是相当常见的。今天对一些高级用法进行一个简单的说明,希望能给大家一些启发。
1 使用cacheFile分发文件
如果文件(如字典文件)存放在HDFS中,希望计算时在每个计算节点上将文件当作本地文件处理,,可以使用-cacheFile hdfs://host:port/path/to/file#linkname选项在计算节点缓存文件,Streaming程序通过./linkname访问文件。
例如:
hadoop = `which hadoop`
$hadoop streaming \
-input /user/test/input -output /user/test/output \
-mapper mymapper.sh -reducer myreducer.sh \
-file /home/work/mymapper.sh \
-file /home/work/myreducer.sh \
-cacheFile hdfs://namenode:port/user/test/dict.data#dictlink \
-jobconf mapred.job.name=”cache-file-demo”
mymapper.sh和myreducer.sh可以通过./dictlink直接访问字典文件hdfs://user/test/dict.data,而且是从本地读取文件。
2 用cacheArchive分发压缩包
有时要分发的文件有一定的目录结构,可以先将整个目录打包,然后整体进行上传。使用-cacheArchive hdfs://host:port/path/to/archivefile#linkname分发压缩包。
例如在本地有一个目录为app,里面有mapper.pl, reducer.pl, dict/dict.txt这些子目录和文件,mapper.pl和reducer.pl要读取./dict/dict.txt文件,希望在任务执行时不需要修改程序和目录结构, 可以按照下面的方式分发app目录:
$ tar app.tar.gz –C app . #本地打包
$ $HADOOP_HOME/bin/hadoop fs –put app.tar.gz /user/test/app.tar.gz #包上传到HDFS
$ $HADOOP_HOME/bin/hadoop streaming \
-input /user/test/input -output /user/test/output \
-mapper “perl app/mapper.pl” -reducer “perl app/reducer.pl” \
-cacheArchive hdfs://namenode:port/user/test/ app.tar.gz #app \
-jobconf mapred.job.name=”cache-archive-demo”
首先将本地app目录中的所有文件和目录打包压缩,然后上传到HDFS的/user/test/app.tar.gz,启动streaming任务时使用-cacheArchive选项将app.tar.gz分发到计算节点并解压到app目录,然后在当前工作目录创建到app目录的链接,-mapper选项指定app/mapper.pl为mapper程序,-reducer选项指定app/reducer.pl为reducer程序,它们都可以读取./dict/dict.txt文件。本地打包时要进入目录app而不是在app的上层目录打包,否则要通过app/app/mapper.pl才能访问到mapper.pl文件。
hadoop支持zip, jar, tar.gz格式的压缩包,由于Java解压zip压缩包时会丢失文件权限信息而且遇到中文文件名会出错,所见建议采用tar.gz压缩包。
三种文件分发方式的区别:-file将客户端本地文件打成jar包上传到HDFS然后分发到计算节点,-cacheFile将HDFS文件分发到计算节点,-cacheArchive将HDFS压缩文件分发到计算节点并解压。
3输出数据分割
默认情况下Streaming框架将map输出的每一行第一个”\t”之前的部分作为key,之后的部分作为value,key\tvalue又作为reduce的输入。可以用-D stream.map.output.field.separator改变map输出中key和value的分隔符,用-D stream.num.map.output.key.fields设置分隔符的位置,该位置之前的部分作为key,之后的部分作为value。如下所示,其中-D stream.map. output.field.separator=:指定使用冒号”:”将map输出的一行分隔为key/value,-D stream.num.map.output.key.fields=2指定在第二个冒号处进行分隔,也就是第二个冒号之前的作为key,之后的作为value。如果没有冒号或冒号少于两个,则key为整行,value为空。
$HADOOP_HOME/bin/hadoop streaming \
-D stream.map.output.field.separator=: \
-D stream.num.map.output.key.fields=2 \
-input /user/test/input -output /user/test/output \
-mapper mymapper.sh -reducer myreducer.sh \
-file /home/work/mymapper.sh \
-file /home/work/myreducer.sh \
-jobconf mapred.job.name=”output-sep-demo”
与map类似,对于reduce的输出,同样也可以用-D stream.reduce.output.field.separator和-D stream.num.reduce.output.key.fields定制key/value分隔方式。
4 二次排序
KeyFieldBasedPartitioner是Hadoop库中的一个实用Partitioner,配置相应的参数就可以使用,通过KeyFieldBasedPartitioner可以方便地实现二次排序。
$HADOOP_HOME/bin/hadoop streaming \
-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 \
-input /user/test/input -output /user/test/output \
-mapper “mymapper.sh” -reducer “ myreducer.sh” \
-partitioner org.apache.hadoop.mapred.lib.KeyFieldBasedPartitioner \
-file /home/work/mymapper.sh \
-file /home/work/myreducer.sh \
-jobconf mapred.job.name=”key-partition-demo”
其中-Dstream.map.output.field.separator=.和-D stream.num.map.output.key.fields=4与上面的定制输出数据分隔方式意义相同,指定map的输出行第4个英文句号”.”之前为key,后面为value。-partitioner org.apache.hadoop.mapred.lib.KeyFieldBasedPartitioner指定使用KeyFieldBasedPartitioner,-D map.output.key.field.separator=.指定key的内部用英文句号”.”分隔,-D num.key.fields.for.partition=2指定将key分隔出来的前两个部分而不是整个key用于Partitioner做partition。
以上就是我个人认为hadoop streaming中比较常用的技巧,希望对大家有所帮助,同时也多多补充。
- hadoop streaming (shell执行 & combiner & 数据分割)
- hadoop学习;Streaming,aggregate;combiner
- hadoop streaming 输出数据分割与二次排序
- Hadoop Streaming 输出文件分割
- hadoop-combiner
- Hadoop之Combiner与自定义Combiner(笔记8)
- Hadoop Streaming 实战: 输出文件分割
- Hadoop Streaming 实战: 输出文件分割
- Hadoop Streaming 实战: 输出文件分割
- Hadoop Streaming 实战: 输出文件分割
- Hadoop学习笔记(三):Combiner funcitons
- Hadoop(三)自定义combiner和partitioner
- 学习Hadoop第十六课(Combiner编程)
- Hadoop Streaming shell 脚本命令汇总
- 【hadoop】Hadoop学习笔记(三):Combiner funcitons
- Hadoop执行shell脚本
- Hadoop的combiner尝试
- Hadoop Combiner 操作
- 剑指Offer-8
- Python三大神器之pip的安装
- 【git系列之E】git的分支操作(查看分支、切换分支、新建分支和删除分支)
- [RK3288][Android6.0] ALSA的DMA buffer读写位置更新
- codevs 3342 绿色通道(二分+dp+优先队列or单调队列)好题
- hadoop streaming (shell执行 & combiner & 数据分割)
- javascript 位置,尺寸,溢出
- 使用Apache POI生成和解析Excel文件
- Nginx 配置部分详述
- 【OpenCV】邻域滤波:方框、高斯、中值、双边滤波
- 在servlet中使用jasperreport展示报表
- 【R语言可视化】R语言画爱心图
- 安卓商品展示
- “集体智慧编程”之第六章:文档过滤的基础和朴素贝叶斯分类器