Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2176665
  • 博文数量: 104
  • 博客积分: 206
  • 博客等级: 入伍新兵
  • 技术积分: 1829
  • 用 户 组: 普通用户
  • 注册时间: 2012-09-12 10:24
个人简介

效字当先,以质为本。测试开发入行十余年,辉煌过,迷茫过,持续探寻人生的激情和前进的步伐!好好生活,认真工作!

文章分类
文章存档

2024年(1)

2019年(2)

2018年(4)

2017年(7)

2016年(3)

2015年(14)

2014年(33)

2013年(31)

2012年(9)

分类: Python/Ruby

2017-11-27 18:30:31

最近有个需求,就是对视频日志中的部分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.py

2、报各种命令错误如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的工作流程大概如下:

  1. hadoop-streaming.jar向Hadoop集群注册一个新的job,传入input path和output path等
  2. 开始mapper时,Hadoop Streaming会将输入文件按行传入stdin
  3. 我们自己编写的mapper需要读取stdin每一行,对其进行处理
  4. mapper处理完毕的中间结果也要写入stdout,在Python中print语句默认即输出到stdout,当然若是不放心,也可以手动指定输出流。对于输出到stdout中的每一行,hadoop将默认以’\t’作为分隔符切割成k-v的格式。
  5. mapper处理结束后,Hadoop 自动进行partition、sort、group,准备进行reduce任务
  6. Hadoop Streaming将中间结果按行传给reducer
  7. 我们编写的reducer需要读取stdin的每一行,对其进行处理
  8. 处理结束之后仍然输出到stdout中
  9. Hadoop 转存到output path中
  10. 结束
最后:
我们一般在本地调试的话,用这条命令就可以了: 
cat part-00001 |python mapper.py |sort|python reducer.py
part-00001为要执行的文件。调试通过后再去集群上执行;
map代码示例:

点击(此处)折叠或打开

  1. import json
  2. import sys
  3. import pattern

  4. def map():
  5.     patterns = {}
  6.     urls = []
  7.     for line in sys.stdin:
  8.         line = line.strip()
  9.         #print line
  10.         json_obj = json.loads(line)
  11.         play_url = json_obj['play_url'].strip()
  12.         if play_url != "":
  13.             urlpatter = pattern.hand_url(play_url)
  14.             if urlpatter not in patterns.keys():
  15.                 patterns[urlpatter] = [play_url]
  16.             else:
  17.                 patterns[urlpatter].append(play_url)
  18.     for i in patterns.keys():
  19.         print "%s\t%s"%(i,patterns[i])


  20. if __name__ == '__main__':
  21.     map()
reduce代码示例(只是示例,暂未做随机挑选5条的功能):

点击(此处)折叠或打开

  1. import sys

  2. def reducer():
  3.     for line in sys.stdin:
  4.         #print line
  5.         key,value = line.rstrip('\n').split('\t')
  6.         print key,value


  7. if __name__ == "__main__":
  8.     reducer()











阅读(20689) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~