Algorithm 当k个元素不适合内存时,mapreduce中的top-k

Algorithm 当k个元素不适合内存时,mapreduce中的top-k,algorithm,sorting,hadoop,mapreduce,Algorithm,Sorting,Hadoop,Mapreduce,当k太大而无法容纳内存中的k个元素时,从数据集中查找top-k元素的高效MapReduce算法是什么?我说的是一个包含数百万个元素的数据集,k就是其中的3/4。假设每个元素都有一个值,我们希望找到具有最高值的k个元素 例如,表格中的数据: e1:5 e2:10 e3:7 e4:8 然后,前2名是e4和e2(不关心它们的相关顺序) 我见过,但它没有规模。 显然,使用单个减速机同样是不实际的(内存不足错误)。这可能不是最有效的,但它易于理解和实现 MapReduce第1阶段: 将减速器的数量设置为1

当k太大而无法容纳内存中的k个元素时,从数据集中查找top-k元素的高效MapReduce算法是什么?我说的是一个包含数百万个元素的数据集,k就是其中的3/4。假设每个元素都有一个值,我们希望找到具有最高值的k个元素

例如,表格中的数据:

e1:5

e2:10

e3:7

e4:8

然后,前2名是e4和e2(不关心它们的相关顺序)

我见过,但它没有规模。
显然,使用单个减速机同样是不实际的(内存不足错误)。

这可能不是最有效的,但它易于理解和实现

MapReduce第1阶段: 将减速器的数量设置为1

  • 映射:读取输入(键k,值v)对并将它们发送到 键为v、值为k的减速器
  • Reduce:当数据通过数据库发送时,shuffle阶段将根据数值(因为它们是键)对数据进行排序 网络。数据将到达减速器,减速器将按排序顺序输出单个文件
MapReduce第2阶段:不需要reduce阶段

  • 映射:读取单个已排序的文件并输出前k个元素

如果要选择顶部k,其中k是百分比,然后,您可以在第1阶段映射阶段使用a来计算输入文件中存在的记录数,然后在第2阶段使用另一个计数器来选择最高的k百分比。

这可能不是最有效的,但它易于理解和实现

MapReduce第1阶段: 将减速器的数量设置为1

  • 映射:读取输入(键k,值v)对并将它们发送到 键为v、值为k的减速器
  • Reduce:当数据通过数据库发送时,shuffle阶段将根据数值(因为它们是键)对数据进行排序 网络。数据将到达减速器,减速器将按排序顺序输出单个文件
MapReduce第2阶段:不需要reduce阶段

  • 映射:读取单个已排序的文件并输出前k个元素

如果要选择顶部k,其中k是一个百分比,则可以在第1阶段映射阶段使用a来计算输入文件中存在的记录数,然后在第2阶段使用另一个计数器来选择顶部k百分比。

您需要一种双MR作业方法:

第一份工作:

在映射器中执行所描述的逻辑,以获得减速器中的分组计数。 然后,减速机将计数(作为键)写入键值对(作为值)。如果遇到性能问题,这里的减速器可以并联

第二份工作:

映射器只是映射身份。通过定义一个反向比较器来处理降序排序

这里的单个reducer获取降序排序的数据。 然后,您可以简单地递增,直到点击“k”并发出值


请注意,您可能有相同计数的项目,因此您需要将从减少的值中获得的每个值作为新的“k”进行计数

您需要一种双MR工作方法:

第一份工作:

在映射器中执行所描述的逻辑,以获得减速器中的分组计数。 然后,减速机将计数(作为键)写入键值对(作为值)。如果遇到性能问题,这里的减速器可以并联

第二份工作:

映射器只是映射身份。通过定义一个反向比较器来处理降序排序

这里的单个reducer获取降序排序的数据。 然后,您可以简单地递增,直到点击“k”并发出值


请注意,您可能有相同计数的项目,因此您需要将从减少的值中获得的每个值作为新的“k”进行计数

我想我找到了我要找的东西。答案就在这里:

这个想法是使用一个新的方法。此分区器首先需要采样,可以使用生成采样,例如。我相信,这种采样用于负载平衡,以确保所有减速机将获得几乎相同的工作量(数据)

默认分区器(hashPartitioner)的问题是(键,值)对将在其中结束的缩减器基于键的哈希。然后,在每个减速器的输入中进行排序。这并不能保证较大的密钥将由“跟随”减速器处理。 TotalOrderPartitioner保证后者,采样用于负载平衡

数据完全排序后,我们可以选择最后一个k(例如,在unix中对
hadoop dfs-getmerge
的结果使用
tail-k
命令),或者使用反向比较器并选择第一个k,正如Thomas Jungblut所建议的那样。如果我的答案不正确,请随意评论/编辑

编辑:提供了一个更好的示例(在源代码方面)


编辑2:看来这个问题毕竟是一个“经典”问题,汤姆·怀特(Tom White)的书《Hadoop最终指南》(第一版第223页)中的“总体分类”一节也描述了解决方案。你也可以跟随观看免费预览。

我想我找到了我想要的东西。答案就在这里:

这个想法是使用一个新的方法。此分区器首先需要采样,可以使用生成采样,例如。我相信,这种采样用于负载平衡,以确保所有减速机将获得几乎相同的工作量(数据)

默认分区器(hashPartitioner)的问题是(键,值)对将在其中结束的缩减器基于键的哈希。然后,在每个减速器的输入中进行排序。这并不能保证较大的密钥将由“跟随”减速器处理。 这个