用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的分页功能
Mar 21 PHP
深入解析PHP内存管理之谁动了我的内存
Jun 20 PHP
php写的AES加密解密类分享
Jun 20 PHP
推荐一本PHP程序猿都应该拜读的书
Dec 31 PHP
php导入excel文件到mysql数据库的方法
Jan 14 PHP
PHP基于cookie与session统计网站访问量并输出显示的方法
Jan 15 PHP
php实现简单爬虫的开发
Mar 28 PHP
PHP版微信第三方实现一键登录及获取用户信息的方法
Oct 14 PHP
[原创]PHPCMS遭遇会员投稿审核无效的解决方法
Jan 11 PHP
利用ajax和PHP实现简单的流程管理
Mar 23 PHP
PHP addAttribute()函数讲解
Feb 03 PHP
PHP中的Iterator迭代对象属性详解
Apr 12 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设计模式 Proxy (代理模式)
2011/06/26 PHP
CI框架中cookie的操作方法分析
2014/12/12 PHP
分享下php5类中三种数据类型的区别
2015/01/26 PHP
PHP中字符安全过滤函数使用小结
2015/02/25 PHP
Laravel框架实现文件上传的方法分析
2019/09/29 PHP
Laravel 自定命令以及生成文件的例子
2019/10/23 PHP
浮动的div自适应居中显示的js代码
2013/12/23 Javascript
jQuery对JSON数据进行排序输出的方法
2015/06/24 Javascript
用js实现博客打赏功能
2016/10/24 Javascript
jQuery密码强度验证控件使用详解
2017/01/05 Javascript
jQuery阻止移动端遮罩层后页面滚动
2017/03/15 Javascript
通过命令行创建vue项目的方法
2017/07/20 Javascript
Angularjs实现上传图片预览功能
2017/09/01 Javascript
实现图片首尾平滑轮播(JS原生方法—节流)
2017/10/17 Javascript
微信小程序页面间跳转传参方式总结
2019/06/13 Javascript
微信小程序基于Taro的分享图片功能实践详解
2019/07/12 Javascript
jquery分页优化操作实例分析
2019/08/23 jQuery
精确查找PHP WEBSHELL木马的方法(1)
2011/04/12 Python
python的描述符(descriptor)、装饰器(property)造成的一个无限递归问题分享
2014/07/09 Python
使用Python实现一个简单的项目监控
2015/03/31 Python
Pycharm技巧之代码跳转该如何回退
2017/07/16 Python
Python PyQt4实现QQ抽屉效果
2018/04/20 Python
Python中交换两个元素的实现方法
2018/06/29 Python
opencv python 图像去噪的实现方法
2018/08/31 Python
python 同时读取多个文件的例子
2019/07/16 Python
PyQT5 emit 和 connect的用法详解
2019/12/13 Python
python开发实例之Python的Twisted框架中Deferred对象的详细用法与实例
2020/03/19 Python
Python字符串查找基本操作代码案例
2020/10/27 Python
可自定义箭头样式的CSS3气泡提示框
2016/03/16 HTML / CSS
Canvas实现贝赛尔曲线轨迹动画的示例代码
2019/04/25 HTML / CSS
丹尼尔惠灵顿手表天猫官方旗舰店:Daniel Wellington
2017/08/25 全球购物
英语专业应届生求职信范文
2013/11/15 职场文书
银行主办会计岗位职责
2014/08/13 职场文书
银行实习推荐信
2015/03/27 职场文书
舌尖上的中国观后感
2015/06/02 职场文书
干货:如何写好工作总结报告!
2019/05/10 职场文书