用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 相关文章推荐
php mysql数据库操作类
Jun 04 PHP
GBK的页面输出JSON格式的php函数
Feb 16 PHP
基于PHP常用字符串的总结(待续)
Jun 07 PHP
php缩小png图片不损失透明色的解决方法
Dec 25 PHP
php读取mssql的ntext字段返回值为空的解决方法
Dec 30 PHP
php实现兼容2038年后Unix时间戳转换函数
Mar 18 PHP
一张表搞清楚php is_null、empty、isset的区别
Jul 07 PHP
学习php设计模式 php实现门面模式(Facade)
Dec 07 PHP
CentOS下PHP7的编译安装及MySQL的支持和一些常见问题的解决办法
Dec 17 PHP
对laravel的session获取与存取方法详解
Oct 08 PHP
laravel 修改记住我功能的cookie保存时间的方法
Oct 14 PHP
PHP常用函数之base64图片上传功能详解
Oct 21 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
PHP之密码加密的几种方式
2015/07/29 PHP
适用于初学者的简易PHP文件上传类
2015/10/29 PHP
基于JQuery 的消息提示框效果代码
2011/07/31 Javascript
jQuery右键菜单contextMenu使用实例
2011/09/28 Javascript
Javascript实现重力弹跳拖拽运动效果示例
2013/06/28 Javascript
JavaScript根据数据生成百分比图和柱状图的实例代码
2013/07/14 Javascript
JavaScript修改作用域外变量的方法
2016/03/25 Javascript
js和jQuery设置Opacity半透明 兼容IE6
2016/05/24 Javascript
js数组的五种迭代方法及两种归并方法(推荐)
2016/06/14 Javascript
jQuery实现下拉菜单(内容为时间)的实时更新及图表的随动更新的方法
2016/07/07 Javascript
javascript工厂模式和构造函数模式创建对象方法解析
2016/12/30 Javascript
基于Vue过渡状态实例讲解
2017/09/14 Javascript
JavaScript定义函数的三种实现方法
2017/09/23 Javascript
浅谈JsonObject中的key-value数据解析排序问题
2017/12/06 Javascript
jQuery+koa2实现简单的Ajax请求的示例
2018/03/06 jQuery
微信小程序自定义底部弹出框
2020/11/16 Javascript
原生JS实现图片懒加载之页面性能优化
2019/04/26 Javascript
node.js express框架简介与实现
2019/07/23 Javascript
微信小程序 下拉刷新及上拉加载原理解析
2019/11/06 Javascript
[01:03:59]2018DOTA2亚洲邀请赛3月30日 小组赛B组VGJ.T VS Secret
2018/03/31 DOTA
[02:10]DOTA2 TI10勇士令状玩法及不朽Ⅰ展示:焕新世界,如你所期
2020/05/29 DOTA
python实现根据ip地址反向查找主机名称的方法
2015/04/29 Python
Python面向对象特殊成员
2017/04/24 Python
Python实现带参数与不带参数的多重继承示例
2018/01/30 Python
Python实现查找最小的k个数示例【两种解法】
2019/01/08 Python
Python将string转换到float的实例方法
2019/07/29 Python
给你一面国旗 教你用python画中国国旗
2019/09/24 Python
Python pygame绘制文字制作滚动文字过程解析
2019/12/12 Python
Python urllib request模块发送请求实现过程解析
2020/12/10 Python
会计专业毕业生自我评价
2013/09/25 职场文书
社区巾帼文明岗事迹材料
2014/06/03 职场文书
电子信息专业应届生自荐信
2014/06/04 职场文书
普通党员个人对照检查材料
2014/09/18 职场文书
学校政风行风评议工作总结
2014/10/21 职场文书
创业计划书之熟食店
2019/10/16 职场文书
Python 中的Sympy详细使用
2021/08/07 Python