您如何在 map/reduce 中实现排名和排序?
Posted
技术标签:
【中文标题】您如何在 map/reduce 中实现排名和排序?【英文标题】:How do you implement ranking and sorting in map/reduce? 【发布时间】:2012-05-13 03:37:19 【问题描述】:我正在学习 Hadoop 中的 Java map/reduce API,并试图集中精力思考 map/reduce。这是我针对 apache http 服务器日志文件编写的示例程序,它有两个阶段(每个阶段都实现为 M/R 作业,然后链接在一起):
-
统计每个IP地址访问服务器的次数
查找前 5 个 IP 地址(请求最多)
第 1 阶段看起来很简单,它是 map/reduce 中的一个简单计数实现,它发出如下内容:
192.168.0.2 4
10.0.0.2 7
127.0.0.1 3
...etc
此输出将馈送到第二个 map/reduce 作业的映射器。
现在我对如何以并行方式实现前 5 名感到困惑。由于 reducer 本质上是顺序的,我猜只有一个 reducer 会违反完整列表来对其进行排序,对吧?您如何以并行方式解决第 2 步?
【问题讨论】:
【参考方案1】:首先,如果第一个作业的输出足够小以至于您不需要并行化它,请考虑:
hadoop fs -cat joboutput/part-* | sort -k2 -n | head -n5
在很多情况下,这可能比将所有数据都发送到一个 reducer 更快!
当您试图摆脱只使用 1 个 reducer 时,Hadoop 中的排序非常粗糙。如果您对排序感兴趣,请尝试查看TotalOrderPartioner。通过在网上搜索,您应该会找到一些示例。基本解决方案是您必须使用自定义分区器将您的值分区到升值箱中。然后,每个 bin 都会自然排序。你输出,你有一个排序集。
困难的部分是弄清楚如何将数据放入哪些 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 计数)而其他事情会很困难(排序、连接)。只是野兽的本性。
【讨论】:
以上是关于您如何在 map/reduce 中实现排名和排序?的主要内容,如果未能解决你的问题,请参考以下文章