好的 MapReduce 示例 [关闭]
Posted
技术标签:
【中文标题】好的 MapReduce 示例 [关闭]【英文标题】:Good MapReduce examples [closed] 【发布时间】:2012-09-04 17:46:29 【问题描述】:除了“如何使用 MapReduce 计算长文本中的单词”任务之外,我想不出任何好的示例。我发现这并不是让其他人了解此工具的强大功能的最佳示例。
我不是在寻找 code-sn-ps,实际上只是“文本”示例。
【问题讨论】:
我认为一个类似但更好的例子是计算计算机上所有文本文件的字数。更容易理解和展示 MapReduce 的强大功能。 对于我搜索的最后四个问题,我发现它们在本网站上被关闭为非建设性的。幸运的是,他们已经有了答案。我对作者表示感谢,截至目前,已有 80 多人不了解关闭政策。对其他人来说并不重要,但我从 80 年代开始就是一名专业程序员,到现在为止,我发现自己问错了问题:) 值得一看 MapReduce 设计模式:例如these slides 中介绍了一些内容,this book 中可以看到更多内容 【参考方案1】:Map reduce 是一个为高效处理大量数据而开发的框架。 例如,如果我们在一个数据集中有 100 万条记录,并且它以关系表示形式存储 - 派生值并对这些值执行任何类型的转换都是非常昂贵的。
例如在 SQL 中,给定出生日期,找出有多少人的年龄 > 30 岁的一百万条记录将需要一段时间,而且当查询的复杂性增加时,这只会按数量级增加. Map Reduce 提供基于集群的实现,其中数据以分布式方式处理
这是一篇解释 map-reduce
is all about 的***文章
另一个很好的例子是通过 map reduce 寻找朋友是理解这个概念的有力例子,并且 一个很好用的用例。
个人觉得this link对理解这个概念很有用
复制博客中提供的解释(以防链接失效)
寻找朋友
MapReduce 是最初由 Google 开发的框架,它允许 用于跨多个域的轻松大规模分布式计算。 Apache Hadoop 是一个开源实现。
我将掩盖细节,但归结为定义两个 函数:一个map函数和一个reduce函数。地图功能 接受一个值并输出键:值对。例如,如果我们定义 一个 map 函数,它接受一个字符串并输出单词的长度 作为键和单词本身作为值然后 map(steve) 将 返回 5:steve 和 map(savannah) 将返回 8:savannah。你可能有 注意到 map 函数是无状态的,只需要输入 value 来计算它的输出值。这允许我们运行地图 并行地对值起作用,并提供了巨大的优势。 在我们进入reduce函数之前,mapreduce框架组 通过键将所有值组合在一起,因此如果映射函数输出 以下键:值对:
3 : the 3 : and 3 : you 4 : then 4 : what 4 : when 5 : steve 5 : where 8 : savannah 8 : research
它们被分组为:
3 : [the, and, you] 4 : [then, what, when] 5 : [steve, where] 8 : [savannah, research]
然后这些行中的每一行都将作为参数传递给 reduce 函数,它接受一个键和一个值列表。在这种情况下, 我们可能试图弄清楚有多少特定长度的单词 存在,所以我们的reduce函数只会计算项目的数量 列表并输出具有列表大小的键,例如:
3 : 3 4 : 3 5 : 2 8 : 2
减少也可以并行完成,再次提供巨大的 优势。然后我们可以查看这些最终结果并看到 在我们的语料库中只有两个长度为 5 的单词,等等......
mapreduce 最常见的例子是计算 词在语料库中出现的次数。假设你有一份互联网副本 (我很幸运能够在这种情况下工作),并且 你想要一个互联网上每个单词的列表以及有多少 它发生的次数。
您处理此问题的方法是将您的文档标记化 拥有(将其分解为单词),并将每个单词传递给映射器。映射器 然后会将单词连同
1
的值一起吐出。这 分组阶段将获取所有键(在本例中为单词),并制作一个 1 的列表。然后,reduce 阶段需要一个键(单词)和一个列表 (每次密钥出现在互联网上时的 1 列表),以及 总结列表。然后 reducer 输出这个词,连同它的 数数。当一切都说完了,你会得到一个每个单词的列表 互联网,以及它出现的次数。很简单,对吧?如果你曾经读过 mapreduce,上面的场景 不是什么新东西……它是 mapreduce 的“Hello, World”。所以这里是 一个真实世界的用例(Facebook 可能会也可能不会真正做到 以下,只是一个例子):
Facebook 有一个朋友列表(请注意,朋友是双向的 脸书上的事。如果我是你的朋友,你就是我的)。他们还有 大量磁盘空间,它们服务于数亿个请求 每天。他们决定在可能的情况下预先计算 减少请求的处理时间。一种常见的处理请求 是“你和乔有 230 个共同的朋友”功能。当你 访问某人的个人资料,您会看到您拥有的朋友列表 常见的。此列表不会经常更改,因此很浪费 每次访问配置文件时重新计算它(确保您可以使用 一个不错的缓存策略,但是我将无法继续 为这个问题写关于 mapreduce 的文章)。我们将使用 mapreduce 这样我们就可以计算出每个人的共同朋友一次 天并存储这些结果。稍后它只是一个快速查找。我们已经 有很多磁盘,很便宜。
假设好友存储为 Person->[List of Friends],我们的 那么朋友列表是:
A -> B C D B -> A C D E C -> A B D E D -> A B C E E -> B C D
每一行都是映射器的一个参数。送给身边的每一位朋友 好友列表,映射器会输出一个键值对。关键将 与此人成为朋友。该值将是列表 朋友们。键将被排序,以便朋友按顺序排列, 导致所有成对的朋友都去同一个减速器。这很难 用文字解释,所以让我们这样做,看看你是否能看到 图案。在所有映射器运行完毕后,您将拥有一个列表 像这样:
For map(A -> B C D) : (A B) -> B C D (A C) -> B C D (A D) -> B C D For map(B -> A C D E) : (Note that A comes before B in the key) (A B) -> A C D E (B C) -> A C D E (B D) -> A C D E (B E) -> A C D E For map(C -> A B D E) : (A C) -> A B D E (B C) -> A B D E (C D) -> A B D E (C E) -> A B D E For map(D -> A B C E) : (A D) -> A B C E (B D) -> A B C E (C D) -> A B C E (D E) -> A B C E And finally for map(E -> B C D): (B E) -> B C D (C E) -> B C D (D E) -> B C D Before we send these key-value pairs to the reducers, we group them by their keys and get: (A B) -> (A C D E) (B C D) (A C) -> (A B D E) (B C D) (A D) -> (A B C E) (B C D) (B C) -> (A B D E) (A C D E) (B D) -> (A B C E) (A C D E) (B E) -> (A C D E) (B C D) (C D) -> (A B C E) (A B D E) (C E) -> (A B D E) (B C D) (D E) -> (A B C E) (B C D)
每一行都将作为参数传递给reducer。减少 函数将简单地与值列表相交并输出相同的值 键与交集的结果。例如,reduce((A B) -> (A C D E) (B C D)) 将输出 (A B) : (C D) 表示朋友 A 和 B 有 C 和 D 作为共同的朋友。
还原后的结果是:
(A B) -> (C D) (A C) -> (B D) (A D) -> (B C) (B C) -> (A D E) (B D) -> (A C E) (B E) -> (C D) (C D) -> (A B E) (C E) -> (B D) (D E) -> (B C)
现在当 D 访问 B 的个人资料时,我们可以快速查找
(B D)
并查看 他们有三个共同的朋友,(A C E)
。
【讨论】:
另一个例子是分析来自世界各地的天气数据。查找任何给定区域的最大值和最小值。这是一个很好的例子。 生成所有这些中间元组,然后检查所有的交集,这不是很乏味吗?只生成所有可能的朋友对,例如 AB AC BC 等,然后将这些对与整个朋友列表(仅对中的两个朋友)传递给特定机器并让它计算交集不是更好吗?我在这里错过了什么? 如果 A 访问 E 的个人资料怎么办?尽管他们有共同的朋友,但最终结果中没有(A,E)。 @Pinch 那是因为 A 和 E 本身不是朋友。在那种情况下,这种方法似乎确实不够(除非您考虑到 A 或 E 可以为非朋友隐藏他们的好友列表:)) @karthikr :我对分组阶段感到困惑。 Map 和 Reduce 显然可以并行运行,但是分组阶段呢?它必须在一个线程中完成,或者我错过了什么?【参考方案2】:One of the best examples of Hadoop-like MapReduce implementation.
请记住,尽管它们仅限于 MapReduce 理念的基于键值的实现(因此它们的适用性受到限制)。
【讨论】:
你是对的。但现实世界中的大多数问题都是基于键值的,或者可以/应该转化为键值范式。【参考方案3】:您可以在 MapReduce 中执行的一组熟悉的操作是一组普通的 SQL 操作:SELECT、SELECT WHERE、GROUP BY 等。
另一个很好的例子是矩阵乘法,你传递一行 M 和整个向量 x 并计算 M * x 的一个元素。
【讨论】:
【参考方案4】:我不时向人们展示 MR 概念。我发现人们熟悉的处理任务,然后将它们映射到 MR 范例。
通常我会做两件事:
分组依据/聚合。在这里,洗牌阶段的优势是显而易见的。解释洗牌也是分布式排序+分布式排序算法的解释也有帮助。
两个表的联接。使用 DB 的人熟悉这个概念及其可伸缩性问题。展示如何在 MR 中完成。
【讨论】:
向非书呆子解释我使用儿童方法:你有一群热心的孩子,还有很多很多卡片。你给每个孩子一定数量的卡片,告诉他们按卡片背面*甲板排序,然后按数字/图片,然后按套装 - 即每个孩子完成并带给一组分配的成年人的地图功能,一次两张。每个成年人将牌堆“减少”成一堆,然后每两个成年人给一个免费的成年人那里的牌堆。根据定义,reduce 函数可以根据孩子/堆栈的数量运行多次。大多数人第一次尝试就知道了以上是关于好的 MapReduce 示例 [关闭]的主要内容,如果未能解决你的问题,请参考以下文章
使用 mapred 或 mapreduce 包创建 Hadoop 作业哪个更好?
Hadoop MapReduce 官方教程 -- WordCount示例