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.shmyreducer.sh可以通過./dictlink直接訪問字典文件hdfs://user/test/dict.data,而且是從本地讀取文件。

 

  2cacheArchive分發壓縮包

  有時要分發的文件有一定的目錄結構,可以先將整個目錄打包,然后整體進行上傳。使用 -cacheArchive hdfs://host:port/path/to/archivefile#linkname分發壓縮包。

例如在本地有一個目錄為app,里面有mapper.pl, reducer.pl, dict/dict.txt這些子目錄和文件,mapper.plreducer.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.plmapper程序,-reducer選項指定app/reducer.plreducer程序,它們都可以讀取./dict/dict.txt文件。本地打包時要進入目錄app而不是在app的上層目錄打包,否則要通過app/app/mapper.pl才能訪問到mapper.pl文件。

hadoop支持zip, jar, tar.gz格式的壓縮包,由於Java解壓zip壓縮包時會丟失文件權限信息而且遇到中文文件名會出錯,所見建議采用tar.gz壓縮包。

三種文件分發方式的區別:-file將客戶端本地文件打成jar包上傳到HDFS然后分發到計算節點,-cacheFileHDFS文件分發到計算節點,-cacheArchiveHDFS壓縮文件分發到計算節點並解壓。


3輸出數據分割

默認情況下Streaming框架將map輸出的每一行第一個”\t”之前的部分作為key,之后的部分作為valuekey\tvalue又作為reduce的輸入。可以用-D stream.map.output.field.separator改變map輸出中keyvalue的分隔符,用-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 二次排序

  KeyFieldBasedPartitionerHadoop庫中的一個實用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用於Partitionerpartition

  以上就是我個人認為hadoop streaming中比較常用的技巧,希望對大家有所幫助,同時也多多補充。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM