用python + hadoop streaming 分布式編程(一) -- 原理介紹,樣例程序與本地調(diào)試
MapReduce與HDFS簡(jiǎn)介
什么是Hadoop?
Google為自己的業(yè)務(wù)需要提出了編程模型MapReduce和分布式文件系統(tǒng)Google File System,并發(fā)布了相關(guān)論文(可在Google Research的網(wǎng)站上獲得: GFS 、 MapReduce)。 Doug Cutting和Mike Cafarella在開發(fā)搜索引擎Nutch時(shí)對(duì)這兩篇論文做了自己的實(shí)現(xiàn),即同名的MapReduce和HDFS,合起來(lái)就是Hadoop。
MapReduce的Data flow如下圖,原始數(shù)據(jù)經(jīng)過(guò)mapper處理,再進(jìn)行partition和sort,到達(dá)reducer,輸出最后結(jié)果。
圖片來(lái)自Hadoop: The Definitive Guide
Hadoop Streaming原理
Hadoop本身是用Java開發(fā)的,程序也需要用Java編寫,但是通過(guò)Hadoop Streaming,我們可以使用任意語(yǔ)言來(lái)編寫程序,讓Hadoop運(yùn)行。
Hadoop Streaming的相關(guān)源代碼可以在Hadoop的Github repo 查看。簡(jiǎn)單來(lái)說(shuō),就是通過(guò)將用其他語(yǔ)言編寫的mapper和reducer通過(guò)參數(shù)傳給一個(gè)事先寫好的Java程序(Hadoop自帶的*-streaming.jar),這個(gè)Java程序會(huì)負(fù)責(zé)創(chuàng)建MR作業(yè),另開一個(gè)進(jìn)程來(lái)運(yùn)行mapper,將得到的輸入通過(guò)stdin傳給它,再將mapper處理后輸出到stdout的數(shù)據(jù)交給Hadoop,partition和sort之后,再另開進(jìn)程運(yùn)行reducer,同樣地通過(guò)stdin/stdout得到最終結(jié)果。因此,我們只需要在其他語(yǔ)言編寫的程序里,通過(guò)stdin接收數(shù)據(jù),再將處理過(guò)的數(shù)據(jù)輸出到stdout,Hadoop streaming就能通過(guò)這個(gè)Java的wrapper幫我們解決中間繁瑣的步驟,運(yùn)行分布式程序。
圖片來(lái)自Hadoop: The Definitive Guide
原理上只要是能夠處理stdio的語(yǔ)言都能用來(lái)寫mapper和reducer,也可以指定mapper或reducer為L(zhǎng)inux下的程序(如awk、grep、cat)或者按照一定格式寫好的java class。因此,mapper和reducer也不必是同一類的程序。
Hadoop Streaming的優(yōu)缺點(diǎn)
優(yōu)點(diǎn)
可以使用自己喜歡的語(yǔ)言來(lái)編寫MapReduce程序(換句話說(shuō),不必寫Java XD)
不需要像寫Java的MR程序那樣import一大堆庫(kù),在代碼里做一大堆配置,很多東西都抽象到了stdio上,代碼量顯著減少
因?yàn)闆](méi)有庫(kù)的依賴,調(diào)試方便,并且可以脫離Hadoop先在本地用管道模擬調(diào)試
缺點(diǎn)
只能通過(guò)命令行參數(shù)來(lái)控制MapReduce框架,不像Java的程序那樣可以在代碼里使用API,控制力比較弱,有些東西鞭長(zhǎng)莫及
因?yàn)橹虚g隔著一層處理,效率會(huì)比較慢
所以Hadoop Streaming比較適合做一些簡(jiǎn)單的任務(wù),比如用python寫只有一兩百行的腳本。如果項(xiàng)目比較復(fù)雜,或者需要進(jìn)行比較細(xì)致的優(yōu)化,使用Streaming就容易出現(xiàn)一些束手束腳的地方。
用python編寫簡(jiǎn)單的Hadoop Streaming程序
這里提供兩個(gè)例子:
Michael Noll的word count程序
Hadoop: The Definitive Guide里的例程
使用python編寫Hadoop Streaming程序有幾點(diǎn)需要注意:
在能使用iterator的情況下,盡量使用iterator,避免將stdin的輸入大量?jī)?chǔ)存在內(nèi)存里,否則會(huì)嚴(yán)重降低性能
streaming不會(huì)幫你分割key和value傳進(jìn)來(lái),傳進(jìn)來(lái)的只是一個(gè)個(gè)字符串而已,需要你自己在代碼里手動(dòng)調(diào)用split()
從stdin得到的每一行數(shù)據(jù)末尾似乎會(huì)有\(zhòng)n,保險(xiǎn)起見一般都需要使用rstrip()來(lái)去掉
在想獲得K-V list而不是一個(gè)個(gè)處理key-value pair時(shí),可以使用groupby配合itemgetter將key相同的k-v pair組成一個(gè)個(gè)group,得到類似Java編寫的reduce可以直接獲取一個(gè)Text類型的key和一個(gè)iterable作為value的效果。注意itemgetter的效率比lambda表達(dá)式要高,所以如果需求不是很復(fù)雜的話,盡量用itemgetter比較好。
我在編寫Hadoop Streaming程序時(shí)的基本模版是
#!/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()
如果對(duì)輸入輸出格式有不同于默認(rèn)的控制,主要會(huì)在read_input()里調(diào)整。
本地調(diào)試
本地調(diào)試用于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>
這里有幾點(diǎn)需要注意:
Hadoop默認(rèn)按照tab來(lái)分割key和value,以第一個(gè)分割出的部分為key,按key進(jìn)行排序,因此這里使用
sort -t $'\t' -k1,1
來(lái)模擬。如果你有其他需求,在交給Hadoop Streaming執(zhí)行時(shí)可以通過(guò)命令行參數(shù)調(diào),本地調(diào)試也可以進(jìn)行相應(yīng)的調(diào)整,主要是調(diào)整sort的參數(shù)。因此為了能夠熟練進(jìn)行本地調(diào)試,建議先掌握sort命令的用法。
如果你在python腳本里加上了shebang,并且為它們添加了執(zhí)行權(quán)限,也可以用類似于
./mapper.py
來(lái)代替
python mapper.py
- Python 程序報(bào)錯(cuò)崩潰后如何倒回到崩潰的位置(推薦)
- 如何使用repr調(diào)試python程序
- 解決pycharm的Python console不能調(diào)試當(dāng)前程序的問(wèn)題
- 利用Pycharm斷點(diǎn)調(diào)試Python程序的方法
- 對(duì)python程序內(nèi)存泄漏調(diào)試的記錄
- 使用pdb模塊調(diào)試Python程序?qū)嵗?/a>
- 調(diào)試Python程序代碼的幾種方法總結(jié)
- 使用PDB簡(jiǎn)單調(diào)試Python程序簡(jiǎn)明指南
- Python 如何調(diào)試程序崩潰錯(cuò)誤
相關(guān)文章
python Pandas如何對(duì)數(shù)據(jù)集隨機(jī)抽樣
這篇文章主要介紹了python Pandas如何對(duì)數(shù)據(jù)集隨機(jī)抽樣,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-07-07Pytorch Tensor的統(tǒng)計(jì)屬性實(shí)例講解
今天小編就為大家分享一篇Pytorch Tensor的統(tǒng)計(jì)屬性實(shí)例講解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-12-12一文搞懂Python中pandas透視表pivot_table功能
透視表是一種可以對(duì)數(shù)據(jù)動(dòng)態(tài)排布并且分類匯總的表格格式。或許大多數(shù)人都在Excel使用過(guò)數(shù)據(jù)透視表,也體會(huì)到它的強(qiáng)大功能,而在pandas中它被稱作pivot_table,今天通過(guò)本文給大家介紹Python中pandas透視表pivot_table功能,感興趣的朋友一起看看吧2021-11-11Python數(shù)據(jù)分析的八種處理缺失值方法詳解
缺失值可能是數(shù)據(jù)科學(xué)中最不受歡迎的值,然而,它們總是在身邊。忽略缺失值也是不合理的,因此我們需要找到有效且適當(dāng)?shù)靥幚硭鼈兊姆椒?/div> 2021-11-11Python中使用filter過(guò)濾列表的一個(gè)小技巧分享
這篇文章主要介紹了Python中使用filter過(guò)濾列表的一個(gè)小技巧分享,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-05-05啟動(dòng)Atom并運(yùn)行python文件的步驟
在本篇文章中我們給大家分享了啟動(dòng)Atom并運(yùn)行python文件的步驟以及具體做法,需要的朋友們參考下。2018-11-11django 信號(hào)調(diào)度機(jī)制詳解
這篇文章主要介紹了django 信號(hào)調(diào)度機(jī)制詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-07-07django開發(fā)post接口簡(jiǎn)單案例,獲取參數(shù)值的方法
今天小編就為大家分享一篇django開發(fā)post接口簡(jiǎn)單案例,獲取參數(shù)值的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-12-12最新評(píng)論