python还是hadoop_使用Python和Hadoop Streaming编写MapReduce

最近有个需求,就是对视频日志中的部分URL提取出来,并随机挑选五条。由于线上日志比较大,而且需要每天执行一次,如果单纯的用python即便是多线程性能也会大大折扣。于是考虑到用hadoop的MR去实现。

准备工作:

1、hadoop集群;

2、mapper和reducer划分;

初步把提取url的操作划分为mapper中执行,随机挑选5条由reducer去执行。

首先看下MR的工作原理:

上图是MR的workflow,在介绍Hadoop Streaming的时候,可以拿来做参照。

Hadoop 和 MapReduce已经如日中天。Hadoop 不仅可以使用Java进行MapReduce的编写,也通过Hadoop Streaming的方式提供了其他语言编写MR的接口。更重要的是,使用python来编写MR,比使用亲儿子Java编写MR要更简单和方便……所以在一些不非常复杂的任务中使用python来编写MR比起使用Java,是更加划算的。Hadoop Streaming:

Hadoop Streaming提供了一个便于进行MapReduce编程的工具包,使用它可以基于一些可执行命令、脚本语言或其他编程语言来实现Mapper和 Reducer,从而充分利用Hadoop并行计算框架的优势和能力。Hadoop Streaming比较独特的一点是利用的UNIX标准输入输出stdin和stdout,所以只要能处理stdin和stdout的编程语言都能够使用Hadoop Streaming来进行MR的编写。甚至,wc、awk这些linux自带的能处理标准输入输出的程序,也能被用来编写Hadoop Streaming。怎么工作的呢:Hadoop Streaming 提供了一个hadoop-streaming.jar,默认处于$HADOOP_HOME目录下。如果不在可以自己搜索下,然后使用Hadoop 执行该jar,传入MR job 的参数们开始MapReduce。一个最基本的使用Hadoop Streaming来执行MR的命令行如下:

/home/xitong/software/hadoop-0.20.2.1U29/bin/hadoop  jar \

/home/xitong/software/hadoop-0.20.2.1U29/contrib/streaming/hadoop-streaming.jar \

-input /user/eng-test/vidio  -output /user/eng-test/vidiooutnew  \

-mapper  /home/eng-test/donhiyue/mapper.py  \

-reducer /home/eng-test/donhiyue/reducer.py

这时候我们执行下上面的命令,这个时候会报错:1、sh: /home/eng-test/donhiyue/mapper.py: 没有那个文件或目录

这里因为map是需要分发给下面的各个slave去执行的,所以有个文件拷贝的动作,这里加上-file就可以了,于是命令变为如下:

/home/xitong/software/hadoop-0.20.2.1U29/bin/hadoop jar /home/xitong/software/hadoop-0.20.2.1U29/contrib/streaming/hadoop-streaming.jar

-input /user/eng-test/vidio  -output /user/eng-test/vidiooutnew3

-file/home/eng-test/dongshiyue/mapper.py

-file/home/eng-test/dongiyue/reducer.py

-mapper  /home/eng-test/dongiyue/mapper.py

-reducer /home/eng-test/dongshiyue/reducer.py2、报各种命令错误如import失败等,是因为-mapper 应该用Python执行

/home/xitong/software/hadoop-0.20.2.1U29/bin/hadoop jar /home/xitong/software/hadoop-0.20.2.1U29/contrib/streaming/hadoop-streaming.jar

-input /user/eng-test/vidio  -output /user/eng-test/vidiooutnew3

-file/home/eng-test/dongshiyue/mapper.py

-file/home/eng-test/dongiyue/reducer.py

-mapper  “python /home/eng-test/dongiyue/mapper.py"

-reducer  "python /home/eng-test/dongshiyue/reducer.py

总结下流程:

Hadoop Streaming的工作流程大概如下:

hadoop-streaming.jar向Hadoop集群注册一个新的job,传入input path和output path等

开始mapper时,Hadoop Streaming会将输入文件按行传入stdin

我们自己编写的mapper需要读取stdin每一行,对其进行处理

mapper处理完毕的中间结果也要写入stdout,在Python中print语句默认即输出到stdout,当然若是不放心,也可以手动指定输出流。对于输出到stdout中的每一行,hadoop将默认以’\t’作为分隔符切割成k-v的格式。

mapper处理结束后,Hadoop 自动进行partition、sort、group,准备进行reduce任务

Hadoop Streaming将中间结果按行传给reducer

我们编写的reducer需要读取stdin的每一行,对其进行处理

处理结束之后仍然输出到stdout中

Hadoop 转存到output path中

结束

最后:

我们一般在本地调试的话,用这条命令就可以了:

cat part-00001 |python mapper.py |sort|python reducer.py

part-00001为要执行的文件。调试通过后再去集群上执行;

map代码示例:

点击(此处)折叠或打开

import json

import sys

import pattern

def map():

patterns = {}

urls = []

for line in sys.stdin:

line = line.strip()

#print line

json_obj = json.loads(line)

play_url = json_obj['play_url'].strip()

if play_url != "":

urlpatter = pattern.hand_url(play_url)

if urlpatter not in patterns.keys():

patterns[urlpatter] = [play_url]

else:

patterns[urlpatter].append(play_url)

for i in patterns.keys():

print "%s\t%s"%(i,patterns[i])

if __name__ == '__main__':

map()

reduce代码示例(只是示例,暂未做随机挑选5条的功能):

点击(此处)折叠或打开

import sys

def reducer():

for line in sys.stdin:

#print line

key,value = line.rstrip('\n').split('\t')

print key,value

if __name__ == "__main__":

reducer()

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值