你如何在map / reduce中实现排名和排序?

时间:2012-05-13 03:37:20

标签: hadoop mapreduce

我正在学习Hadoop中的Java map / reduce API,并尝试在map / reduce中思考。这是我正在针对apache http服务器日志文件编写的示例程序,它有两个阶段(每个阶段都实现为M / R作业然后链接在一起):

  1. 计算每个IP地址访问服务器的次数
  2. 查找前5个IP地址(大多数请求)

    阶段1看起来非常简单,它是map / reduce中的简单计数实现,它会发出如下内容:

    192.168.0.2  4
    10.0.0.2  7
    127.0.0.1  3
    ...etc
    
  3. 此输出将输入第二个map / reduce作业的映射器。

    现在我对如何以并行方式实现前5名感到困惑。由于Reducer本质上是顺序的,我猜测只有一个reducer会违反完整列表来排序,对吧?你如何以平行的方式解决第2步?

1 个答案:

答案 0 :(得分:1)

首先,如果第一个作业的输出足够小而不需要并行化,请考虑:

hadoop fs -cat joboutput/part-* | sort -k2 -n | head -n5

在很多情况下,这可能比将它全部发送到一个减速器更快!


当您尝试远离仅使用1个reducer时,Hadoop中的排序非常粗糙。如果您对排序感兴趣,请尝试查看TotalOrderPartioner。通过在网上搜索,你应该找到一些例子。根本的解决方案是,您必须使用自定义分区程序将分区您的值分区为升值分区。然后,每个箱子自然分类。你输出了,你有一个有序集。

困难的部分是弄清楚如何将数据放入哪些垃圾箱。


如果你对前5名特别感兴趣(或者前50名,无论如何),有一种有趣的方法可以做到这一点。基本前提是,如果你取每个映射器的前5个,那么在reducer中取前5个的前5个。每个映射器有效地将他们的前五名发送到减速器以竞争真正的前五名,有点像锦标赛。你可以保证在减速机中获得前5名,你只需要把它们中的一些去掉。

为了跟踪mapper和reducer中的前5名,我想使用TreeMap。基本上,继续插入值,并将其截断到顶部5.在Mapper#cleanup方法中,写出前5条记录(不要在map本身写出)。为减速器做同样的事情。


我会在这里插入Apache Pig这样的东西。它可能没有上面的选项那么有效,但它确实更容易编码。

loaded = LOAD 'joboutput/' USING PigStorage('\t') AS (ip:chararray, cnt:int);
sorted = ORDER loaded BY cnt DESC;
top = LIMIT sorted 5;
dump top;

很抱歉,像排序这样简单的事情并不像您在Hadoop中想象的那么简单。有些事情会变得容易(例如,你做的ip计数)和其他事情会变得很难(排序,加入)。只是野兽的本性。