用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代码把全角数字转为半角数字
Dec 10 PHP
对text数据类型不支持代码页转换 从: 1252 到: 936
Apr 23 PHP
php与java通过socket通信的实现代码
Oct 21 PHP
PHP zip扩展Linux下安装过程分享
May 05 PHP
PHP OPP机制和模式简介(抽象类、接口和契约式编程)
Jun 09 PHP
2个Codeigniter文件批量上传控制器写法例子
Jul 25 PHP
PHP获取表单所有复选框的值的方法
Aug 28 PHP
php中mkdir函数用法实例分析
Nov 15 PHP
PDO预处理语句PDOStatement对象使用总结
Nov 20 PHP
PHP中使用substr()截取字符串出现中文乱码问题该怎么办
Oct 21 PHP
如何使用php脚本给html中引用的js和css路径打上版本号
Nov 18 PHP
php报错502badgateway解决方法
Oct 11 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
laravel中的错误与日志用法详解
2016/07/26 PHP
浅析php-fpm静态和动态执行方式的比较
2016/11/09 PHP
PHP使用PDO 连接与连接管理操作实例分析
2020/04/21 PHP
javascript 触发HTML元素绑定的函数
2010/09/11 Javascript
转换字符串为json对象的方法详解
2013/11/29 Javascript
JavaScript类属性的访问方式详解
2014/02/11 Javascript
JS函数this的用法实例分析
2015/02/05 Javascript
jQuery实现宽屏图片轮播实例教程
2015/11/24 Javascript
纯css下拉菜单 无需js
2016/08/15 Javascript
JavaScript 最佳实践:帮你提升代码质量
2016/12/03 Javascript
JavaScript数据结构之单链表和循环链表
2017/11/28 Javascript
基于vue-cli配置lib-flexible + rem实现移动端自适应
2017/12/26 Javascript
8个非常实用的Vue自定义指令
2020/12/15 Vue.js
[00:43]FTP典藏礼包 DOTA2三大英雄霸气新套装
2014/03/21 DOTA
[01:02:00]DOTA2-DPC中国联赛 正赛 Elephant vs IG BO3 第三场 1月24日
2021/03/11 DOTA
Python设计模式之单例模式实例
2014/04/26 Python
Python中实现常量(Const)功能
2015/01/28 Python
详解Python中的__new__()方法的使用
2015/04/09 Python
python实现查找两个字符串中相同字符并输出的方法
2015/07/11 Python
使用python画个小猪佩奇的示例代码
2018/06/06 Python
Python numpy.array()生成相同元素数组的示例
2018/11/12 Python
Python实例方法、类方法、静态方法的区别与作用详解
2019/03/25 Python
python程序控制NAO机器人行走
2019/04/29 Python
Python中使用__new__实现单例模式并解析
2019/06/25 Python
在Django model中设置多个字段联合唯一约束的实例
2019/07/17 Python
HTML5 Canvas 旋转风车绘制
2017/08/18 HTML / CSS
印尼值得信赖的在线交易网站:Bukalapak
2019/03/11 全球购物
kfc实习自我鉴定
2013/12/14 职场文书
幼儿园大班毕业教师寄语
2014/04/03 职场文书
关于安全演讲稿
2014/05/09 职场文书
公司节能减排方案
2014/05/16 职场文书
结对共建协议书
2014/08/20 职场文书
工作批评与自我批评范文
2014/10/16 职场文书
工作失职检讨书
2015/01/26 职场文书
《当代神农氏》教学反思
2016/02/23 职场文书
基于HTML十秒做出淘宝页面
2021/10/24 HTML / CSS