用PHP和Shell寫Hadoop的MapReduce程序
使得任何支持標(biāo)準(zhǔn)IO (stdin, stdout)的可執(zhí)行程序都能成為hadoop的mapper或者 reducer。例如:
hadoop jar hadoop-streaming.jar -input SOME_INPUT_DIR_OR_FILE -output SOME_OUTPUT_DIR -mapper /bin/cat -reducer /usr/bin/wc
在這個(gè)例子里,就使用了Unix/Linux自帶的cat和wc工具來作為mapper / reducer,是不是很神奇?
如果你習(xí)慣了使用一些動(dòng)態(tài)語言,用動(dòng)態(tài)語言來寫mapreduce吧,跟之前的編程沒有任何不同,hadoop只是運(yùn)行它的一個(gè)框架,下面我演示一下用PHP來實(shí)現(xiàn)Word Counter的mapreduce。
一、找到Streaming jar
Hadoop根目錄下是沒有hadoop-streaming.jar的,因?yàn)閟treaming是一個(gè)contrib,所以要去contrib下面找,以hadoop-0.20.2為例,它在這里:
二、寫Mapper
新建一個(gè)wc_mapper.php,寫入如下代碼:
#!/usr/bin/php
<?php
$in = fopen(“php://stdin”, “r”);
$results = array();
while ( $line = fgets($in, 4096) )
{
$words = preg_split(‘/\W/', $line, 0, PREG_SPLIT_NO_EMPTY);
foreach ($words as $word)
$results[] = $word;
}
fclose($in);
foreach ($results as $key => $value)
{
print “$value\t1\n”;
}
這段代碼的大致意思是:把輸入的每行文本中的單詞找出來,并以”
hello 1
world 1″
這樣的形式輸出出來。
和之前寫的PHP基本沒有什么不同,對(duì)吧,可能稍微讓你感到陌生有兩個(gè)地方:
PHP作為可執(zhí)行程序
第一行的“#!/usr/bin/php”告訴linux,要用/usr/bin/php這個(gè)程序作為以下代碼的解釋器。寫過linux shell的人應(yīng)該很熟悉這種寫法了,每個(gè)shell腳本的第一行都是這樣: #!/bin/bash, #!/usr/bin/python
有了這一行,保存好這個(gè)文件以后,就可以像這樣直接把wc_mapper.php當(dāng)作cat, grep一樣的命令執(zhí)行了:./wc_mapper.php
使用stdin接收輸入
PHP支持多種參數(shù)傳入的方法,大家最熟悉的應(yīng)該是從$_GET, $_POST超全局變量里面取通過Web傳遞的參數(shù),次之是從$_SERVER['argv']里取通過命令行傳入的參數(shù),這里,采用的是標(biāo)準(zhǔn)輸入stdin
它的使用效果是:
在linux控制臺(tái)輸入 ./wc_mapper.php
wc_mapper.php運(yùn)行,控制臺(tái)進(jìn)入等候用戶鍵盤輸入狀態(tài)
用戶通過鍵盤輸入文本
用戶按下Ctrl + D終止輸入,wc_mapper.php開始執(zhí)行真正的業(yè)務(wù)邏輯,并將執(zhí)行結(jié)果輸出
那么stdout在哪呢?print本身已經(jīng)就是stdout啦,跟我們以前寫web程序和CLI腳本沒有任何不同。
三、寫Reducer
新建一個(gè)wc_reducer.php,寫入如下代碼:
#!/usr/bin/php
<?php
$in = fopen(“php://stdin”, “r”);
$results = array();
while ( $line = fgets($in, 4096) )
{
list($key, $value) = preg_split(“/\t/”, trim($line), 2);
$results[$key] += $value;
}
fclose($in);
ksort($results);
foreach ($results as $key => $value)
{
print “$key\t$value\n”;
}
這段代碼的大意是統(tǒng)計(jì)每個(gè)單詞出現(xiàn)了多少次,并以”
hello 2
world 1″
這樣的形式輸出。
四、用Hadoop來運(yùn)行
上傳要統(tǒng)計(jì)的示例文本
hadoop fs -put *.TXT /tmp/input
以Streaming方式執(zhí)行PHP mapreduce程序
注意:
input和output目錄是在hdfs上的路徑
mapper和reducer是在本地機(jī)器的路徑,一定要寫絕對(duì)路徑,不要寫相對(duì)路徑,以免到時(shí)候hadoop報(bào)錯(cuò)說找不到mapreduce程序。
查看結(jié)果
五、shell版的Hadoop MapReduce程序
#!/bin/bash -
# 加載配置文件
source './config.sh'
# 處理命令行參數(shù)
while getopts "d:" arg
do
case $arg in
d)
date=$OPTARG
?)
echo "unkonw argument"
exit 1
esac
done
# 默認(rèn)處理日期為昨天
default_date=`date -v-1d +%Y-%m-%d`
# 最終處理日期. 如果日期格式不對(duì), 則退出執(zhí)行
date=${date:-${default_date}}
if ! [[ "$date" =~ [12][0-9]{3}-(0[1-9]|1[12])-(0[1-9]|[12][0-9]|3[01]) ]]
then
echo "invalid date(yyyy-mm-dd): $date"
exit 1
fi
# 待處理文件
log_files=$(${hadoop_home}bin/hadoop fs -ls ${log_file_dir_in_hdfs} | awk '{print $8}' | grep $date)
# 如果待處理文件數(shù)目為零, 則退出執(zhí)行
log_files_amount=$(($(echo $log_files | wc -l) + 0))
if [ $log_files_amount -lt 1 ]
then
echo "no log files found"
exit 0
fi
# 輸入文件列表
for f in $log_files
do
input_files_list="${input_files_list} $f"
done
function map_reduce () {
if ${hadoop_home}bin/hadoop jar ${streaming_jar_path} -input${input_files_list} -output ${mapreduce_output_dir}${date}/${1}/ -mapper "${mapper} ${1}" -reducer "${reducer}" -file "${mapper}"
then
echo "streaming job done!"
else
exit 1
fi
}
# 循環(huán)處理每一個(gè)bucket
for bucket in ${bucket_list[@]}
do
map_reduce $bucket
done
相關(guān)文章
PHP房貸計(jì)算器實(shí)例代碼,等額本息,等額本金
下面小編就為大家?guī)硪黄狿HP房貸計(jì)算器實(shí)例代碼,等額本息,等額本金。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-04-04PHP針對(duì)多用戶實(shí)現(xiàn)更換頭像功能
這篇文章主要介紹了PHP針對(duì)多用戶實(shí)現(xiàn)更換頭像功能的相關(guān)資料,本文分步驟介紹的非常詳細(xì),具有參考借鑒價(jià)值,需要的朋友可以參考下2016-09-09smarty模板引擎中內(nèi)建函數(shù)if、elseif和else的使用方法
這篇文章主要介紹了smarty模板引擎中內(nèi)建函數(shù)if、elseif和else的使用方法,通過兩個(gè)示例分析了if、elseif和else的使用技巧,需要的朋友可以參考下2015-01-01Laravel Intervention/image圖片處理擴(kuò)展包的安裝、使用與可能遇到的坑詳解
這篇文章主要給大家介紹了關(guān)于Laravel中Intervention/image圖片處理擴(kuò)展包的安裝、使用與在使用可能遇到的坑的解決方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。2017-11-11thinkPHP內(nèi)置字符串截取函數(shù)用法詳解
這篇文章主要介紹了thinkPHP內(nèi)置字符串截取函數(shù)用法,結(jié)合實(shí)例形式分析了thinkPHP內(nèi)置的字符串截取函數(shù)功能與具體使用方法,以及針對(duì)無法添加省略號(hào)的源碼修改技巧,需要的朋友可以參考下2016-11-11