用python + hadoop streaming 分布式编程(一) -- 原理介绍,样例程序与本地调试


Posted in Python onJuly 14, 2014

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,输出最后结果。

用python + hadoop streaming 分布式编程(一) -- 原理介绍,样例程序与本地调试

图片来自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帮我们解决中间繁琐的步骤,运行分布式程序。

用python + hadoop streaming 分布式编程(一) -- 原理介绍,样例程序与本地调试

图片来自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程序

这里提供两个例子:

Michael Noll的word count程序
Hadoop: The Definitive Guide里的例程
使用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,1 | python <path to reducer script> > <output path>

或者如果不想用多余的cat,也可以用<定向

$ python <path to mapper script> < <input path> | sort -t $'\t' -k1,1 | python <path to reducer script> > <output path>

这里有几点需要注意:

Hadoop默认按照tab来分割key和value,以第一个分割出的部分为key,按key进行排序,因此这里使用

sort -t $'\t' -k1,1
来模拟。如果你有其他需求,在交给Hadoop Streaming执行时可以通过命令行参数调,本地调试也可以进行相应的调整,主要是调整sort的参数。因此为了能够熟练进行本地调试,建议先掌握sort命令的用法。

如果你在python脚本里加上了shebang,并且为它们添加了执行权限,也可以用类似于

./mapper.py

来代替

python mapper.py
Python 相关文章推荐
Python语言技巧之三元运算符使用介绍
Mar 04 Python
Python编程修改MP3文件名称的方法
Apr 19 Python
django请求返回不同的类型图片json,xml,html的实例
May 22 Python
Python实现深度遍历和广度遍历的方法
Jan 22 Python
Kears+Opencv实现简单人脸识别
Aug 28 Python
Python socket模块方法实现详解
Nov 05 Python
Python基于Socket实现简单聊天室
Feb 17 Python
python实现图片横向和纵向拼接
Mar 05 Python
tensorflow下的图片标准化函数per_image_standardization用法
Jun 30 Python
Python Selenium XPath根据文本内容查找元素的方法
Dec 07 Python
Elasticsearch 批量操作
Apr 19 Python
Python first-order-model实现让照片动起来
Jun 25 Python
用python + openpyxl处理excel2007文档思路以及心得
Jul 14 #Python
Python库urllib与urllib2主要区别分析
Jul 13 #Python
Python文件夹与文件的操作实现代码
Jul 13 #Python
分享15个最受欢迎的Python开源框架
Jul 13 #Python
使用 Python 获取 Linux 系统信息的代码
Jul 13 #Python
Python文件操作类操作实例详解
Jul 11 #Python
Python编写检测数据库SA用户的方法
Jul 11 #Python
You might like
php强制用户转向www域名的方法
2015/06/19 PHP
PHP中each与list用法分析
2016/01/08 PHP
ThinkPHP类似AOP思想的参数验证的实现方法
2019/12/18 PHP
Nigma vs Liquid BO3 第二场2.14
2021/03/10 DOTA
JavaScript 空位补零实现代码
2010/02/26 Javascript
jquery validate.js表单验证的基本用法入门
2010/05/13 Javascript
js中巧用cssText属性批量操作样式
2011/03/13 Javascript
服务器端的JavaScript脚本 Node.js 使用入门
2012/03/07 Javascript
php对mongodb的扩展(小试牛刀)
2012/11/11 Javascript
纯css+js写的一个简单的tab标签页带样式
2014/01/28 Javascript
JavaScript获取网页中第一个链接ID的方法
2015/04/03 Javascript
jQuery给元素添加样式的方法详解
2015/12/30 Javascript
jQGrid动态填充select下拉框的选项值(动态填充)
2016/11/28 Javascript
jQuery基于闭包实现的显示与隐藏div功能示例
2018/06/09 jQuery
javascript中一些奇葩的日期换算方法总结
2018/11/14 Javascript
react脚手架如何配置less和ant按需加载的方法步骤
2018/11/28 Javascript
超详细动手搭建一个VuePress 站点及开启PWA与自动部署的方法
2019/01/27 Javascript
微信小程序实现星级评价
2019/11/20 Javascript
vue iview实现动态新增和删除
2020/06/17 Javascript
vantUI 获得piker选中值的自定义ID操作
2020/11/04 Javascript
[01:14]2014DOTA2展望TI 剑指西雅图newbee战队专访
2014/06/30 DOTA
python解决Fedora解压zip时中文乱码的方法
2016/09/18 Python
python使用Tkinter实现在线音乐播放器
2018/01/30 Python
python计算两个数的百分比方法
2018/06/29 Python
python实现音乐播放器 python实现花框音乐盒子
2020/02/25 Python
python 用struct模块解决黏包问题
2020/11/07 Python
CSS3 @keyframes简单动画实现
2018/02/24 HTML / CSS
教师专业理论水平的自我评价分享
2013/11/09 职场文书
光信息科学与技术专业职业生涯规划
2014/03/13 职场文书
党建工作先进材料
2014/05/02 职场文书
2015年中秋节活动总结
2015/03/23 职场文书
小学教学工作总结2015
2015/05/13 职场文书
vue 实现上传组件
2021/05/31 Vue.js
详细聊聊MySQL中慢SQL优化的方向
2021/08/30 MySQL
SpringBoot实现quartz定时任务可视化管理功能
2021/08/30 Java/Android
Win11绿屏怎么办?Win11绿屏死机的解决方法
2021/11/21 数码科技