首先,如果第一个作业的输出足够小以至于您不需要并行化它,请考虑:
hadoop fs -cat joboutput/part-* | sort -k2 -n | head -n5
在许多情况下,这可能比将其全部发送到一个减速器要快!
当您试图摆脱仅使用 1 个 reducer 时,Hadoop 中的排序非常粗糙。如果您对排序感兴趣,请尝试查看TotalOrderPartioner。通过在网上搜索,您应该会找到一些示例。基本解决方案是您必须使用自定义分区器将值分区到升值箱中。然后,每个 bin 都会自然排序。你输出,你有一个排序集。
困难的部分是弄清楚如何将数据放入哪些箱中。
如果您对前 5 名(或前 50 名,等等)感兴趣,有一种有趣的方法可以做到这一点。基本前提是,如果取每个mapper的top 5,那么取reducer中top 5的top 5。每个 mapper 都有效地将他们的前五名发送给 reducer,以争夺真正的前五名,有点像锦标赛。您可以保证在减速器中获得前 5 名,您只需将其中一些剔除即可。
为了跟踪 mapper 和 reducer 中的 top-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 计数),而有些事情会很困难(排序、连接)。只是野兽的本性。