用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学习 字符串课件
Jun 15 PHP
如何给phpcms v9增加类似于phpcms 2008中的关键词表
Jul 01 PHP
php 发送带附件邮件示例
Jan 23 PHP
PHP生成不重复随机数的方法汇总
Nov 19 PHP
PHP strtotime函数用法、实现原理和源码分析
Feb 04 PHP
PHP使用CURL实现多线程抓取网页
Apr 30 PHP
CentOS下搭建PHP环境与WordPress博客程序的全流程总结
May 07 PHP
PHP编写的图片验证码类文件分享
Jun 06 PHP
PHP获取当前文件的父目录方法汇总
Jul 21 PHP
浅谈PHP发送HTTP请求的几种方式
Jul 25 PHP
thinkPHP框架实现类似java过滤器的简单方法示例
Sep 05 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+dojo 的数据库保存拖动布局的一个方法dojo 这里下载
2007/03/07 PHP
php读取xml实例代码
2010/01/28 PHP
php中的观察者模式
2010/03/24 PHP
zend api扩展的php对象的autoload工具
2011/04/18 PHP
CentOS 6.2使用yum安装LAMP以及phpMyadmin详解
2013/06/17 PHP
php下Memcached入门实例解析
2015/01/05 PHP
基于PHP给大家讲解防刷票的一些技巧
2015/11/18 PHP
js页面滚动时层智能浮动定位实现(jQuery/MooTools)
2011/08/23 Javascript
js查找某元素中的所有图片地址的方法
2014/01/16 Javascript
详解JavaScript中数组的相关知识
2015/07/29 Javascript
解析Node.js异常处理中domain模块的使用方法
2016/02/16 Javascript
浅析C/C++,Java,PHP,JavaScript,Json数组、对象赋值时最后一个元素后面是否可以带逗号
2016/03/22 Javascript
JS在一定时间内跳转页面及各种刷新页面的实现方法
2016/05/26 Javascript
JS简单去除数组中重复项的方法
2016/09/13 Javascript
详解vue跨组件通信的几种方法
2017/06/15 Javascript
element ui table 增加筛选的方法示例
2018/11/02 Javascript
JavaScript数据结构与算法之检索算法实例分析【顺序查找、最大最小值、自组织查询】
2019/02/22 Javascript
es6 filter() 数组过滤方法总结
2019/04/03 Javascript
ES6学习笔记之字符串、数组、对象、函数新增知识点实例分析
2020/01/22 Javascript
webpack3.0升级4.0的方法步骤
2020/04/02 Javascript
JavaScript日期库date-fn.js使用方法解析
2020/09/09 Javascript
Vant 在vue-cli 4.x中按需加载操作
2020/11/05 Javascript
Python中Django 后台自定义表单控件
2017/03/28 Python
Python编程判断一个正整数是否为素数的方法
2017/04/14 Python
Python面向对象之反射/自省机制实例分析
2018/08/24 Python
Pandas之MultiIndex对象的示例详解
2019/06/25 Python
python 处理微信对账单数据的实例代码
2019/07/19 Python
python应用文件读取与登录注册功能
2019/09/23 Python
python 实现两个npy档案合并
2020/07/01 Python
Python如何将模块打包并发布
2020/08/30 Python
Python try except else使用详解
2021/01/12 Python
全球领先的鞋类零售商:The Walking Company
2016/07/21 全球购物
应届毕业生个人求职自荐信
2014/01/06 职场文书
手机促销活动方案
2014/02/05 职场文书
优秀教师先进个人事迹材料
2014/08/31 职场文书
公司承诺函范文
2015/01/21 职场文书