用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执行速度全攻略
Oct 09 PHP
基于AppServ,XAMPP,WAMP配置php.ini去掉警告信息(NOTICE)的方法详解
May 07 PHP
PHP输出缓存ob系列函数详解
Mar 11 PHP
PHP判断表单复选框选中状态完整例子
Jun 24 PHP
PHP Reflection API详解
May 12 PHP
使用PHP similar text计算两个字符串相似度
Nov 06 PHP
简要剖析PHP的Yii框架的组件化机制的基本知识
Mar 17 PHP
php通过PHPExcel导入Excel表格到MySQL数据库的简单实例
Oct 29 PHP
PHP更安全的密码加密机制Bcrypt详解
Jun 18 PHP
PHP常用操作类之通信数据封装类的实现
Jul 16 PHP
浅析PHP中的闭包和匿名函数
Dec 25 PHP
浅析PHP 中move_uploaded_file 上传中文文件名失败
Apr 17 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实现MVC开发得最简单的方法――模型
2007/04/10 PHP
php外部执行命令函数用法小结
2016/10/11 PHP
PHP面向对象程序设计OOP继承用法入门示例
2016/12/27 PHP
详解php实现页面静态化原理
2017/06/21 PHP
php ajax confirm 删除实例详解
2019/03/06 PHP
JavaScript 事件对象的实现
2009/07/13 Javascript
Jquery获得控件值的三种方法总结
2014/02/13 Javascript
详解JavaScript的Polymer框架中的通知交互
2015/07/29 Javascript
JavaScript高级教程5.6之基本包装类型(详细)
2015/11/23 Javascript
动态创建按钮的JavaScript代码
2016/01/29 Javascript
ES6中如何使用Set和WeakSet
2016/03/10 Javascript
BootStrap学习系列之布局组件(下拉,按钮组[toolbar],上拉)
2017/01/03 Javascript
JS实现DIV高度自适应窗口示例
2017/02/16 Javascript
javascript trie前缀树的示例
2018/01/29 Javascript
js代码规范之Eslint安装与配置详解
2018/09/08 Javascript
vue中引入mxGraph的步骤详解
2019/05/17 Javascript
javascript使用正则表达式实现注册登入校验
2020/09/23 Javascript
[02:20]DOTA2英雄基础教程 黑暗贤者
2013/12/19 DOTA
python复制与引用用法分析
2015/04/08 Python
Python利用matplotlib.pyplot绘图时如何设置坐标轴刻度
2018/04/09 Python
Django中使用Celery的教程详解
2018/08/24 Python
python矩阵/字典实现最短路径算法
2019/01/17 Python
Python3中函数参数传递方式实例详解
2019/05/05 Python
pyqt5 删除layout中的所有widget方法
2019/06/25 Python
Python 保持登录状态进行接口测试的方法示例
2019/08/06 Python
Python利用pip安装tar.gz格式的离线资源包
2020/09/14 Python
Python+OpenCV图像处理—— 色彩空间转换
2020/10/22 Python
利用python实现后端写网页(flask框架)
2021/02/28 Python
纯CSS3打造动感漂亮时尚的扇形菜单
2014/03/18 HTML / CSS
CSS3解析抖音LOGO制作的方法步骤
2019/04/11 HTML / CSS
纯CSS3实现运行时钟的示例代码
2021/01/25 HTML / CSS
美国羊皮公司:Overland
2018/01/15 全球购物
Eagle Eyes Optics鹰眼光学:高性能太阳镜
2018/12/07 全球购物
工伤事故证明
2014/10/20 职场文书
工作时间擅自离岗检讨书
2014/10/24 职场文书
vue使用v-model进行跨组件绑定的基本实现方法
2021/04/28 Vue.js