我们知道,一个典型的Map-Reduce过程包 括:Input->Map->Partition->Reduce->Output。

Partition负责把Map任务输出的中间结果 按key分发给不同的Reduce任务进行处理。

Hadoop 提供了一个很有用的partitioner类KeyFieldBasedPartitioner,通过配置对应的參数就能够使用。通过 KeyFieldBasedPartitioner能够方便地实现二次排序。 

用法: 

      -partitioner org.apache.hadoop.mapred.lib.KeyFieldBasedPartitioner 

一般配合: 

      -D map.output.key.field.separator

-D num.key.fields.for.partition使用。 

map.output.key.field.separator指定key内部的分隔符 

num.key.fields.for.partition指定对key分出来的前几部分做partition而不是整个key

演示样例: 

1. 编写map程序mapper.sh;reduce程序reducer.sh; 測试数据test.txt

mapper.sh:

#!/bin/sh  cat

reducer.sh:

#!/bin/sh  sort

test.txt内容:

1,2,1,1,1

1,2,2,1,1

1,3,1,1,1

1,3,2,1,1

1,3,3,1,1

1,2,3,1,1

1,3,1,1,1

1,3,2,1,1

1,3,3,1,1

2. 測试数据test.txt放入hdfs,执行map-reduce程序

$ hadoop streaming /

-D stream.map.output.field.separator=, /

-D stream.num.map.output.key.fields=4 /

-D map.output.key.field.separator=, /

-D num.key.fields.for.partition=2 /

-partitioner org.apache.hadoop.mapred.lib.KeyFieldBasedPartitioner /

-input /app/test/test.txt  /

-output /app/test/test_result / 

-mapper ./mapper.sh  /

-reducer ./reducer.sh /

-file mapper.sh /

-file reducer.sh /

-jobconf mapre.job.name="sep_test"

$ hadoop fs –cat /app/test/test_result/part-00003

1,2,1,1     1

1,2,2,1     1

1,2,3,1     1

$ hadoop fs –cat /app/test/test_result/part-00004

1,3,1,1     1

1,3,1,1     1

1,3,2,1     1

1,3,2,1     1

1,3,3,1     1

1,3,3,1     1

通过这样的方式,就做到前4个字段是key,可是通过前两个字段进行partition的目的

注意:
-D map.output.key.field.separator=, /  

这个分隔符使用TAB键貌似无论用

Hadoop Streaming 是一个工具, 取代编写Java的实现类,而利用可运行程序来完毕map-reduce过程

工作流程 : 



InputFile --> mappers --> [Partitioner] --> reducers -->
outputFiles



理解 : 

1 输入文件,能够是指定远程文件系统内的目录下的 *

2 通过集群自己分解到各个PC上,每一个mapper是一个可运行文件,对应的启动一个进程,来实现你的逻辑

3 mapper 的输入为标准输入,所以,不论什么可以支持标准输入的可运行的东西,c,c++(编译出来的可运行文件),python,......都可以作
为mapper 和 reducer mapper的输出为标准输出,假设有Partitioner,就给它,假设没有,它的输出将作为reducer的输入

4 Partitioner 为可选的项,二次排序,能够对结果进行分类打到结果文件中面,它的输入是mapper的标准输出,它的输出,将作为reducer的标准输入

5 reducer 同 mapper

6 输出目录,在远端文件不能重名



Hadoop Streaming



1 : hadoop-streaming.jar 的位置 : $HADOOP_HOME/contrib/streaming




官方上面关于hadoop-streaming 的介绍已经非常具体了,并且也有了关于python的样例,我就不说了,这里总结下自己的经验



1 指定 mapper or reducer 的 task 官方上说要用 -jobconf 可是这个參数已经过时,不能够用了,官方说要用
-D, 注意这个-D是要作为最開始的配置出现的,由于是在maper 和 reducer 运行之前,就须要硬性指定好的,所以要出如今參数的最前面 ./bin/hadoop jar hadoop-0.19.2-streaming.jar -D .........-input ........ 类似这样,这样,即使你程序最后仅仅指定了一个输出管道,可是还是会有你指定的task数量的结果文件,仅仅只是多余的就是空的 实验下面 就知道了



2 关于二次排序,因为是用的streaming 所以,在可运行文件内,仅仅可以处理逻辑,还有就是输出,当然我们也可以指定二次排序,可是因为是所有參数化,不是非常灵活。比方:

10.2.3.40    1

11.22.33.33    1

www.renren.com 1

www.baidu.com    1

10.2.3.40    1



这样一个非常规整的输入文件,需求是要把记录独立的ip和url的count 可是输出文件要分切割出来。



官方站点的样例,是指定 key 然后对key 指定 主-key 和 key 用来排序,而 主-key 用来二次排序,这样会输出你想要的东西, 可是对于上面最简单的需求,对于传递參数,我们怎样做呢?



事实上我们还是能够利用这一点,在我们mapper 里面,还是依照/t来切割key value 可是我们要给key指定一个主-key 用来给Partitioner
来实现二次排序,所以我们能够略微处理下这个KEY,我们能够简单的推断出来ip 和 url 的差别,这样,我们就人为的加上一个主-key 我们在mapper里面,给每一个key人为的加上一个"标签",用来给partitioner做 二次排序用,比方我们的mapper的输出是这样



D&10.2.3.40    1

D&11.22.33.33    1

W&www.renren.com 1

W&www.baidu.com    1

D&10.2.3.40    1 



然后通过传递命令參数

-partitioner org.apache.hadoop.mapred.lib.KeyFieldBasedPartitioner //指定要求二次排序
-jobconf map.output.key.field.separator='&' //这里假设不加两个单引號的话我的命令会死掉
-jobconf num.key.fields.for.partition=1 //这里指第一个 & 符号来切割,保证不会出错 这样我们就能够通过 partitioner 来实现二次排序了 在reducer里面,我们再把"标签"摘掉(不费吹灰之力)就能够做到悄无声息的完毕二次排序了。 3: 关于模块化 (强调 : 没有在集群上測试,仅仅在单机上做測试) 程序猿最悲剧的就是不能代码复用,做这个也一样,用hadoop-streaming 也一样,要做到代码重用,是我第一个考虑的问题
当我看到 -file(具体能够看官方站点上的解说) 的时候,我就想到利用这个东西,果然,我的在本机上建立了一个py模块,简单的一个函数
然后在我的mapper里面import 它,本地測试通过后,利用-file 把模块所在的问价夹用 -file moudle/* 这个參数,传入streaming
运行的结果毫无错误,这样,我们就能够抽象出来一些模块的东西,来实现我们模块化的需求 注 : 不要忘记 chmod +x *.py  将py 变成可运行的,不然不能够运行 代码 :  1: 模块代码 mg.py 用来给 mapper 贴标签
def mgFunction(line):

        if(line[0] >= '0' and line[0] <= '9'):

                return "D&" + line

        return "W&" + line
2: mapper.py 
#!/usr/bin/env python

import sys

sys.path.append('/home/liuguoqing/Desktop/hadoop-0.19.2/moudle')

import mg

for line in sys.stdin:

        line = mg.mgFunction(line)

        line = line.strip()

#       print line

        words = line.split()

        print '%s\t%s' % (words[0], words[1])

3: reducer.py

#!/usr/bin/env python

import sys

user_login_day = {}



for line in sys.stdin:

        line = line[2:]//去掉帽子

        line = line.strip()

        userid, day = line.split('\t', 1)

        user_login_day[userid] = user_login_day.get(userid, 0) + 1



for uid in user_login_day.keys(): 

        print '%s\t%d' % (uid, user_login_day[uid])

这样就实现了模块化的能够二次排序的hadoop-streaming



命令 



./bin/hadoop jar hadoop-0.19.2-streaming.jar \

#streaming jar

-D mapred.reduce.tasks=2  \

#指定2个reduce来处理

-input user_login_day-input2/*  \

#指定输入文件 能够用 dir/* 方式

-output user_login_day-output102 

#指定输出目录

-mapper ~/Desktop/hadoop-0.19.2/python/mapper/get_user_login_day_back.py  \

#指定mapper 可运行文件 我用全路径,好像用相对路径会出错...

-reducer ~/Desktop/hadoop-0.19.2/python/reducer/get_user_login_day_back.py
\

#指定reducer 可运行文件 

-file ~/Desktop/hadoop-0.19.2/moudle/* \

#指定模块化的库文件 dir/* 模式

-partitioner
org.apache.hadoop.mapred.lib.KeyFieldBasedPartitioner \此处报错-partitioner:
command not found


#指定 partitioner 參数为class

-jobconf map.output.key.field.separator='&' \

#指定 主-key 的切割符号为 '&'

-jobconf num.key.fields.for.partition=1 

#指定为第一个‘&’



liuguoqing@liuguoqing-desktop:~/Desktop/hadoop-0.19.2$
./bin/hadoop jar hadoop-0.19.2-streaming.jar -D mapred.reduce.tasks=2 -input user_login_day-input2/* -output user_login_day-output102 -mapper ~/Desktop/hadoop-0.19.2/python/mapper/get_user_login_day_back.py -reducer ~/Desktop/hadoop-0.19.2/python/reducer/get_user_login_day_back.py
-file ~/Desktop/hadoop-0.19.2/moudle/* -partitioner org.apache.hadoop.mapred.lib.KeyFieldBasedPartitioner -jobconf map.output.key.field.separator='&' -jobconf num.key.fields.for.partition=1

10/01/24 03:19:15 WARN streaming.StreamJob: -jobconf option
is deprecated, please use -D instead.

packageJobJar: [/home/liuguoqing/Desktop/hadoop-0.19.2/moudle/mg.py,
/home/liuguoqing/Desktop/hadoop-0.19.2/moudle/mg.pyc, /tmp/hadoop-liuguoqing/hadoop-unjar6780057097425964518/] [] /tmp/streamjob3100401358387519950.jar tmpDir=null

10/01/24 03:19:15 INFO mapred.FileInputFormat: Total input
paths to process : 2

10/01/24 03:19:15 INFO streaming.StreamJob: getLocalDirs():
[/tmp/hadoop-liuguoqing/mapred/local]

10/01/24 03:19:15 INFO streaming.StreamJob: Running job:
job_201001221008_0065

10/01/24 03:19:15 INFO streaming.StreamJob: To kill this
job, run:

10/01/24 03:19:15 INFO streaming.StreamJob: /home/liuguoqing/Desktop/hadoop-0.19.2/bin/../bin/hadoop
job  -Dmapred.job.tracker=hdfs://localhost:9881 -kill job_201001221008_0065

10/01/24 03:19:15 INFO streaming.StreamJob: Tracking URL:
http://localhost:50030/jobdetails.jsp?jobid=job_201001221008_0065

10/01/24 03:19:16 INFO streaming.StreamJob:  map 0%  reduce
0%

10/01/24 03:19:17 INFO streaming.StreamJob:  map 33%  reduce
0%

10/01/24 03:19:18 INFO streaming.StreamJob:  map 67%  reduce
0%

10/01/24 03:19:19 INFO streaming.StreamJob:  map 100%  reduce
0%

10/01/24 03:19:27 INFO streaming.StreamJob:  map 100%  reduce
50%

10/01/24 03:19:32 INFO streaming.StreamJob:  map 100%  reduce
100%

10/01/24 03:19:32 INFO streaming.StreamJob: Job complete:
job_201001221008_0065

10/01/24 03:19:32 INFO streaming.StreamJob: Output: user_login_day-output102

liuguoqing@liuguoqing-desktop:~/Desktop/hadoop-0.19.2$
./bin/hadoop dfs -ls user_login_day-output102

Found 3 items

drwxr-xr-x   - liuguoqing supergroup          0
2010-01-24 03:19 /user/liuguoqing/user_login_day-output102/_logs

-rw-r--r--   1 liuguoqing supergroup         25
2010-01-24 03:19 /user/liuguoqing/user_login_day-output102/part-00000

-rw-r--r--   1 liuguoqing supergroup         47
2010-01-24 03:19 /user/liuguoqing/user_login_day-output102/part-00001



liuguoqing@liuguoqing-desktop:~/Desktop/hadoop-0.19.2$
./bin/hadoop dfs -cat user_login_day-output102/part-00000

54321    2

99999    1

12345    12

liuguoqing@liuguoqing-desktop:~/Desktop/hadoop-0.19.2$
./bin/hadoop dfs -cat user_login_day-output102/part-00001

http://www.renren.com    3

http://www.baidu.com    3



以上为操作结果显示

python 实现Hadoop的partitioner和二次排序的更多相关文章

  1. Hadoop学习之自定义二次排序

    一.概述    MapReduce框架对处理结果的输出会根据key值进行默认的排序,这个默认排序可以满足一部分需求,但是也是十分有限的.在我们实际的需求当中,往 往有要对reduce输出结果进行二次排 ...

  2. 分别使用Hadoop和Spark实现二次排序

    零.序(注意本部分与标题无太大关系,可直接调至第一部分) 既然没用为啥会有序?原因不想再开一篇文章,来抒发点什么感想或者计划了,就在这里写点好了: 前些日子买了几本书,打算学习和研究大数据方面的知识, ...

  3. Hadoop Mapreduce分区、分组、二次排序过程详解[转]

    原文地址:Hadoop Mapreduce分区.分组.二次排序过程详解[转]作者: 徐海蛟 教学用途 1.MapReduce中数据流动   (1)最简单的过程:  map - reduce   (2) ...

  4. Hadoop.2.x_高级应用_二次排序及MapReduce端join

    一.对于二次排序案例部分理解 1. 分析需求(首先对第一个字段排序,然后在对第二个字段排序) 杂乱的原始数据 排序完成的数据 a,1 a,1 b,1 a,2 a,2 [排序] a,100 b,6 == ...

  5. Hadoop MapReduce 二次排序原理及其应用

    关于二次排序主要涉及到这么几个东西: 在0.20.0 以前使用的是 setPartitionerClass setOutputkeyComparatorClass setOutputValueGrou ...

  6. Hadoop Mapreduce分区、分组、二次排序

    1.MapReduce中数据流动   (1)最简单的过程:  map - reduce   (2)定制了partitioner以将map的结果送往指定reducer的过程: map - partiti ...

  7. 一起学Hadoop——二次排序算法的实现

    二次排序,从字面上可以理解为在对key排序的基础上对key所对应的值value排序,也叫辅助排序.一般情况下,MapReduce框架只对key排序,而不对key所对应的值排序,因此value的排序经常 ...

  8. Hadoop案例(八)辅助排序和二次排序案例(GroupingComparator)

    辅助排序和二次排序案例(GroupingComparator) 1.需求 有如下订单数据 订单id 商品id 成交金额 0000001 Pdt_01 222.8 0000001 Pdt_05 25.8 ...

  9. 如何使用Hadoop的Partitioner

    如何使用Hadoop的Partitioner 博客分类: Hadoop hadooppartition Hadoop里面的MapReduce编程模型,非常灵活,大部分环节我们都可以重写它的API,来灵 ...

随机推荐

  1. 20165301 2017-2018-2 《Java程序设计》第七周学习总结

    20165301 2017-2018-2 <Java程序设计>第七周学习总结 教材学习内容总结 第十一章:JDBC与MySQL数据库 MySQL数据库管理系统 启动MySQL数据库服务器 ...

  2. for循环练习题(共六道题)

    第一题: 假设一个简单的ATM机的取款过程是这样的:首先提示用户输入密码(password),最多只能输入三次,超过3次则提示用户“密码错误,请取卡”结束交易.如果用户密码正确,再提示用户输入取款金额 ...

  3. 借助svn进行半自动多台服务器上线部署

    传统简单保留 如果web服务器就那么几台,大致可以在测试服务器上测试好以后,直接在正式的web服务器 压缩拷贝一个,然后再覆盖下,进行简单暴力的发布. 这种纯手工发布往往会带来几个问题 压缩一不小心把 ...

  4. viewpager切换耗时控制

    原文地址https://my.oschina.net/javalover/blog/179003 public class FixedSpeedScroller extends Scroller { ...

  5. python爬虫实战(四)--------豆瓣网的模拟登录(模拟登录和验证码的处理----scrapy)

    在利用scrapy框架爬各种网站时,一定会碰到某些网站是需要登录才能获取信息. 这两天也在学习怎么去模拟登录,通过自己码的代码和借鉴别人的项目,调试成功豆瓣的模拟登录,顺便处理了怎么自动化的处理验证码 ...

  6. Am335x SD卡 启动制作

    1.网上下载DiskGenius(分区工具) 2.将4Gsd卡分区3个,boot,rootfs,user 3.boot分区大概在62M左右如图所示 将编译好的MLO.u-boot.img.uEnv.t ...

  7. C和指针之学习笔记(2)

    第6章 指针 1.在一组字符串中查找字符: #include<stdio.h> #include<assert.h> #include<stdlib.h> #def ...

  8. 【BZOJ 2054】 2054: 疯狂的馒头 (并查集特技)

    Input 第一行四个正整数N,M,p,q Output 一共输出N行,第i行表示第i个馒头的最终颜色(如果最终颜色是白色就输出0). Sample Input 4 3 2 4 Sample Outp ...

  9. CUDA学习笔记1:第一个CUDA实例

    一.cuda简介 CUDA是支持c++/c语言,一般我喜欢用c来写,他的编译是gpu部分由nvcc来进行的   一般的函数定义 void  function(); cuda的函数定义 __global ...

  10. ARC 058

    所以为啥要写来着........... 链接 T1 直接枚举大于等于$n$的所有数,暴力分解判断即可 复杂度$O(10n \log n)$ #include <cstdio> #inclu ...