用python + hadoop streaming 编写分布式程序(一) -- 原理介绍,样例程序与本地调试
相关随笔:
- Hadoop-1.0.4集群搭建笔记
- 用python + hadoop streaming 编写分布式程序(二) -- 在集群上运行与监控
- 用python + hadoop streaming 编写分布式程序(三) -- 自定义功能
MapReduce与HDFS简介
什么是Hadoop?
Google为自己的业务需要提出了编程模型MapReduce和分布式文件系统Google File System,并发布了相关论文(可在Google Research的网站上获得: GFS 、 MapReduce)。 Doug Cutting和Mike Cafarella在开发搜索引擎Nutch时对这两篇论文做了自己的实现,即同名的MapReduce和HDFS,合起来就是Hadoop。
MapReduce的Data flow如下图,原始数据经过mapper处理,再进行partition和sort,到达reducer,输出最后结果。

图片来自Hadoop: The Definitive Guide
Hadoop Streaming原理
Hadoop本身是用Java开发的,程序也需要用Java编写,但是通过Hadoop Streaming,我们可以使用任意语言来编写程序,让Hadoop运行。
Hadoop Streaming的相关源代码可以在Hadoop的Github repo 查看。简单来说,就是通过将用其他语言编写的mapper和reducer通过参数传给一个事先写好的Java程序(Hadoop自带的*-streaming.jar),这个Java程序会负责创建MR作业,另开一个进程来运行mapper,将得到的输入通过stdin传给它,再将mapper处理后输出到stdout的数据交给Hadoop,partition和sort之后,再另开进程运行reducer,同样地通过stdin/stdout得到最终结果。因此,我们只需要在其他语言编写的程序里,通过stdin接收数据,再将处理过的数据输出到stdout,Hadoop streaming就能通过这个Java的wrapper帮我们解决中间繁琐的步骤,运行分布式程序。

图片来自Hadoop: The Definitive Guide
原理上只要是能够处理stdio的语言都能用来写mapper和reducer,也可以指定mapper或reducer为Linux下的程序(如awk、grep、cat)或者按照一定格式写好的java class。因此,mapper和reducer也不必是同一类的程序。
Hadoop Streaming的优缺点
- 优点
- 可以使用自己喜欢的语言来编写MapReduce程序(换句话说,不必写Java XD)
- 不需要像写Java的MR程序那样import一大堆库,在代码里做一大堆配置,很多东西都抽象到了stdio上,代码量显著减少
- 因为没有库的依赖,调试方便,并且可以脱离Hadoop先在本地用管道模拟调试
- 缺点
- 只能通过命令行参数来控制MapReduce框架,不像Java的程序那样可以在代码里使用API,控制力比较弱,有些东西鞭长莫及
- 因为中间隔着一层处理,效率会比较慢
所以Hadoop Streaming比较适合做一些简单的任务,比如用python写只有一两百行的脚本。如果项目比较复杂,或者需要进行比较细致的优化,使用Streaming就容易出现一些束手束脚的地方。
用python编写简单的Hadoop Streaming程序
这里提供两个例子:
使用python编写Hadoop Streaming程序有几点需要注意:
- 在能使用iterator的情况下,尽量使用iterator,避免将stdin的输入大量储存在内存里,否则会严重降低性能
- streaming不会帮你分割key和value传进来,传进来的只是一个个字符串而已,需要你自己在代码里手动调用split()
- 从stdin得到的每一行数据末尾似乎会有\n,保险起见一般都需要使用rstrip()来去掉
- 在想获得K-V list而不是一个个处理key-value pair时,可以使用groupby配合itemgetter将key相同的k-v pair组成一个个group,得到类似Java编写的reduce可以直接获取一个Text类型的key和一个iterable作为value的效果。注意itemgetter的效率比lambda表达式要高,所以如果需求不是很复杂的话,尽量用itemgetter比较好。
我在编写Hadoop Streaming程序时的基本模版是
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Some description here...
""" import sys
from operator import itemgetter
from itertools import groupby def read_input(file):
"""Read input and split."""
for line in file:
yield line.rstrip().split('\t') def main():
data = read_input(sys.stdin)
for key, kviter in groupby(data, itemgetter(0)):
# some code here.. if __name__ == "__main__":
main()
如果对输入输出格式有不同于默认的控制,主要会在read_input()里调整。
本地调试
本地调试用于Hadoop Streaming的python程序的基本模式是:
$ cat <input path> | python <path to mapper script> | sort -t $'\t' -k1, | python <path to reducer script> > <output path>
或者如果不想用多余的cat,也可以用<定向
$ python <path to mapper script> < <input path> | sort -t $'\t' -k1, | python <path to reducer script> > <output path>
这里有几点需要注意:
Hadoop默认按照tab来分割key和value,以第一个分割出的部分为key,按key进行排序,因此这里使用
sort -t $'\t' -k1,
来模拟。如果你有其他需求,在交给Hadoop Streaming执行时可以通过命令行参数调,本地调试也可以进行相应的调整,主要是调整sort的参数。因此为了能够熟练进行本地调试,建议先掌握sort命令的用法。
如果你在python脚本里加上了shebang,并且为它们添加了执行权限,也可以用类似于
./mapper.py
来代替
python mapper.py
推荐阅读
Hadoop Streaming的官方文档,建议通读
Recommendations with hadoop streaming and python
用python + hadoop streaming 编写分布式程序(一) -- 原理介绍,样例程序与本地调试的更多相关文章
- 用python + hadoop streaming 编写分布式程序(二) -- 在集群上运行与监控
写在前面 相关随笔: Hadoop-1.0.4集群搭建笔记 用python + hadoop streaming 编写分布式程序(一) -- 原理介绍,样例程序与本地调试 用python + hado ...
- 用python + hadoop streaming 编写分布式程序(三) -- 自定义功能
又是期末又是实训TA的事耽搁了好久……先把写好的放上博客吧 相关随笔: Hadoop-1.0.4集群搭建笔记 用python + hadoop streaming 编写分布式程序(一) -- 原理介绍 ...
- EXT-JS 6演示样例程序-Login演示样例程序
1. 用Sencha Cmd生成应用程序模版 sencha -sdk /path/to/ExtSDK generate app -classic TutorialApp./Tutoria ...
- 在Ubuntu下构建Bullet以及执行Bullet的样例程序
在Ubuntu下构建Bullet以及执行Bullet的样例程序 1.找到Bullet的下载页,地址是:https://code.google.com/p/bullet/downloads/list 2 ...
- SNF快速开发平台MVC-各种级联绑定方式,演示样例程序(包含表单和表格控件)
做了这么多项目,经常会使用到级联.联动的情况. 如:省.市.县.区.一级分类.二级分类.三级分类.仓库.货位. 方式:有表单需要做级联的,还是表格行上需要做级联操作的. 实现:实现方法也有很多种方式. ...
- Tuxedo安装、配置、以及演示样例程序 (学习网址)
Tuxedo安装.配置.以及演示样例程序 (学习网址): 1.http://liu9403.iteye.com/blog/1415684 2.http://www.cnblogs.com/fnng/a ...
- Java读取Excel文件(包括xls和xlsx)的样例程序
样例程序如下所示,其中: parseXls()函数依赖于jxl,只能读取xls格式文件: parseExcel()函数依赖于apache poi,能够读取xls和xlsx两种格式的文件. jxl的依赖 ...
- Python Socket 编程——聊天室演示样例程序
上一篇 我们学习了简单的 Python TCP Socket 编程,通过分别写服务端和client的代码了解主要的 Python Socket 编程模型.本文再通过一个样例来加强一下对 Socket ...
- Python线程的用法 函数式线程_thread和threading 样例
函数式线程写起来比较简单,但是功能没有threading那么高级,先来个函数式编程样例: #!/usr/bin/python #coding: utf-8 #————————————————————— ...
随机推荐
- 10 ref 和 out 之间的差别
(1) 两者都是按地址传递的,使用后都将改变原来的数值 (2) ref传进去的參数必须在调用前初始化,out不必 (3) ref传进去的參数在函数内部能够直接使用,而out不可 (4) ref传进去的 ...
- 在ios上时间无法parse返回 "Invalid Date"
百度搜索:" ios 上面 new date" 关键字 BUG 描述直接上原码 var psrseDate = Date.parse("2010-03-15 10:30: ...
- 万恶之源 - Python初识函数
什么是函数 我们目前为止,已经可以完成一些软件的基本功能了,那么我们来完成这样一个功能:约x pint("拿出手机") print("打开陌陌") print( ...
- [py]列表生成式-支持条件,多值的拼接
列表生成式 代码简洁一些 支持多条件, 过滤,或拼接某些值 支持返回多值 是一种生成式 # 生成一个列表 print(list(range(1, 11))) # 生成一个列表x^2 ## 方法1: 返 ...
- oj2892(字典树)
一改时间以后WA了,我就知道这题是考字典树,可惜代码怎么也不会敲了,郁闷. #include <stdio.h>#include <string.h>#include < ...
- try except else
try except 语句还有一个可选的else子句,如果使用这个子句,那么必须放在所有的except子句之后.这个子句将在try子句没有发生任何异常的时候执行.例如: for arg in sys. ...
- 33. Search in Rotated Sorted Array(二分查找)
Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand. (i.e. ...
- html5shiv.min.js
今日看代码,发现了绝妙的一句,把它记录下来. <!--[if IE]> <script src="http://libs.useso.com/js/html5shiv/3. ...
- 缓存(图像 IO 14.2)
缓存 如果有很多张图片要显示,最好不要提前把所有都加载进来,而是应该当移出屏幕之后立刻销毁.通过选择性的缓存,你就可以避免来回滚动时图片重复性的加载了. 缓存其实很简单:就是存储昂贵计算后的结果(或者 ...
- python 读写压缩文件
gzip 和bz2 模块可以很容易的处理这些文件.两个模块都为open() 函数提供了另外的实现来解决这个问题.比如,为了以文本形式读取压缩文件,可以这样做: # gzip compression i ...