用PHP和Shell写Hadoop的MapReduce程序


Posted in PHP onApril 15, 2014

使得任何支持标准IO (stdin, stdout)的可执行程序都能成为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

在这个例子里,就使用了Unix/Linux自带的cat和wc工具来作为mapper / reducer,是不是很神奇?

如果你习惯了使用一些动态语言,用动态语言来写mapreduce吧,跟之前的编程没有任何不同,hadoop只是运行它的一个框架,下面我演示一下用PHP来实现Word Counter的mapreduce。

一、找到Streaming jar

Hadoop根目录下是没有hadoop-streaming.jar的,因为streaming是一个contrib,所以要去contrib下面找,以hadoop-0.20.2为例,它在这里:

$HADOOP_HOME/contrib/streaming/hadoop-0.20.2-streaming.jar

二、写Mapper

新建一个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基本没有什么不同,对吧,可能稍微让你感到陌生有两个地方:

PHP作为可执行程序

第一行的“#!/usr/bin/php”告诉linux,要用/usr/bin/php这个程序作为以下代码的解释器。写过linux shell的人应该很熟悉这种写法了,每个shell脚本的第一行都是这样: #!/bin/bash, #!/usr/bin/python

有了这一行,保存好这个文件以后,就可以像这样直接把wc_mapper.php当作cat, grep一样的命令执行了:./wc_mapper.php

使用stdin接收输入

PHP支持多种参数传入的方法,大家最熟悉的应该是从$_GET, $_POST超全局变量里面取通过Web传递的参数,次之是从$_SERVER['argv']里取通过命令行传入的参数,这里,采用的是标准输入stdin

它的使用效果是:

在linux控制台输入 ./wc_mapper.php

wc_mapper.php运行,控制台进入等候用户键盘输入状态

用户通过键盘输入文本

用户按下Ctrl + D终止输入,wc_mapper.php开始执行真正的业务逻辑,并将执行结果输出

那么stdout在哪呢?print本身已经就是stdout啦,跟我们以前写web程序和CLI脚本没有任何不同。

三、写Reducer

新建一个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”;
}

这段代码的大意是统计每个单词出现了多少次,并以”
hello 2
world 1″
这样的形式输出。

四、用Hadoop来运行

上传要统计的示例文本

hadoop fs -put *.TXT /tmp/input

以Streaming方式执行PHP mapreduce程序

hadoop jar hadoop-0.20.2-streaming.jar -input /tmp/input -output /tmp/output -mapper wc_mapper.php的绝对路径 -reducer wc_reducer.php的绝对路径

注意:

input和output目录是在hdfs上的路径

mapper和reducer是在本地机器的路径,一定要写绝对路径,不要写相对路径,以免到时候hadoop报错说找不到mapreduce程序。

查看结果

hadoop fs -cat /tmp/output/part-00000

五、shell版的Hadoop MapReduce程序

#!/bin/bash -
# 加载配置文件
source './config.sh'
# 处理命令行参数
while getopts "d:" arg
do
 case $arg in
  d)
   date=$OPTARG
  ?)
            echo "unkonw argument"
   exit 1
    esac
done
# 默认处理日期为昨天
default_date=`date -v-1d +%Y-%m-%d`
# 最终处理日期. 如果日期格式不对, 则退出执行
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)
# 如果待处理文件数目为零, 则退出执行
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
}
# 循环处理每一个bucket
for bucket in ${bucket_list[@]}
do
 map_reduce $bucket
done
PHP 相关文章推荐
人大复印资料处理程序_补充篇
Oct 09 PHP
php生成的html meta和link标记在body标签里 顶部有个空行
May 18 PHP
从手册去理解分析PHP session机制
Jul 17 PHP
php调用方法mssql_fetch_row、mssql_fetch_array、mssql_fetch_assoc和mssql_fetch_objcect读取数据的区别
Aug 08 PHP
浅谈php安全性需要注意的几点事项
Jul 17 PHP
destoon调用企业会员公司形象图片的实现方法
Aug 21 PHP
thinkphp3.2.2前后台公用类架构问题分析
Nov 25 PHP
php使用ereg验证文件上传的方法
Dec 16 PHP
PHP实现动态柱状图改进版
Mar 30 PHP
PHP实现的统计数据功能详解
Dec 06 PHP
让Laravel API永远返回JSON格式响应的方法示例
Sep 05 PHP
PHP中16个高危函数整理
Sep 19 PHP
php获取mysql字段名称和其它信息的例子
Apr 14 #PHP
PHP检测移动设备类mobile detection使用实例
Apr 14 #PHP
PHP删除数组中空值的方法介绍
Apr 14 #PHP
PHP批量删除、清除UTF-8文件BOM头的代码实例
Apr 14 #PHP
thinkphp实现数组分页示例
Apr 13 #PHP
不使用php api函数实现数组的交换排序示例
Apr 13 #PHP
php读取大文件示例分享(文件操作类)
Apr 13 #PHP
You might like
smarty的保留变量问题
2008/10/23 PHP
PHP 分页原理分析,大家可以看看
2009/12/21 PHP
PHP中空字符串介绍0、null、empty和false之间的关系
2012/09/25 PHP
PHP实现删除字符串中任何字符的函数
2015/08/11 PHP
php遍历解析xml字符串的方法
2016/05/05 PHP
php简单统计在线人数的方法
2016/05/10 PHP
PHP获取用户客户端真实IP的解决方案
2016/10/10 PHP
javascript call方法使用说明
2010/01/11 Javascript
根据一段代码浅谈Javascript闭包
2010/12/14 Javascript
JavaScript中instanceof运算符的用法总结
2013/11/19 Javascript
JQuery与Ajax调用新浪API获取短网址的代码
2014/02/07 Javascript
jquery获取当前点击对象的value方法
2014/02/28 Javascript
window.onload与$(document).ready()的区别分析
2015/05/30 Javascript
JS添加删除DIV的简单实例
2016/07/08 Javascript
微信小程序 本地存储及登录页面处理实例详解
2017/01/11 Javascript
angular forEach方法遍历源码解读
2017/01/25 Javascript
使用AngularJS2中的指令实现按钮的切换效果
2017/03/27 Javascript
vue.js国际化 vue-i18n插件的使用详解
2017/07/07 Javascript
JavaScript中的return布尔值的用法和原理解析
2017/08/14 Javascript
详解HTML5 使用video标签实现选择摄像头功能
2017/10/25 Javascript
vue + typescript + 极验登录验证的实现方法
2019/06/27 Javascript
javascript中的闭包概念与用法实践分析
2019/07/26 Javascript
jQuery+css实现的点击图片放大缩小预览功能示例【图片预览 查看大图】
2020/05/29 jQuery
快速解决PyCharm无法引用matplotlib的问题
2018/05/24 Python
Pycharm新手教程(只需要看这篇就够了)
2019/06/18 Python
python实现简单图书管理系统
2019/11/22 Python
python nohup 实现远程运行不宕机操作
2020/04/16 Python
python读取excel数据绘制简单曲线图的完整步骤记录
2020/10/30 Python
HTML5样式控制示例代码
2013/11/27 HTML / CSS
详解通过focusout事件解决IOS键盘收起时界面不归位的问题
2019/07/18 HTML / CSS
澳大利亚礼品卡商店:Gift Card Store
2019/06/24 全球购物
入党自荐书范文
2014/03/09 职场文书
副董事长岗位职责
2014/04/02 职场文书
《天安门广场》教学反思
2014/04/23 职场文书
公司投资建议书
2014/05/16 职场文书
小学生安全教育主题班会
2015/08/12 职场文书