1

我无法用 mapreduce 术语表达算法。

我有两个大的输入文本文件:我们称第一个文件为“R”,第二个文件为“P”。R 通常比 P 大得多,但两者都很大。

在非 mapreduce 方法中,P 的内容将被加载到内存中(散列),然后我们将开始迭代 R 中的所有行。R 中的行只是字符串,我们想检查是否有任何子字符串在 R 中匹配 P 中的任何字符串。

该问题与在大文件中查找单词非常相似,问题是单词列表非常大,因此您无法在地图例程中对它们进行硬编码。

我遇到的问题是我不知道如何确保 P 文件的所有拆分最终在每个 R 文件拆分的映射作业中结束。所以,假设这些分裂:

R = R1, R2, R3;
P = P1, P2

6 个地图作业必须包含这些拆分:

(R1, P1) (R1, P2);
(R2, P1) (R2, P2);
(R3, P1) (R3, P2);

你会如何用 mapreduce 术语表达这个问题?

谢谢。

4

2 回答 2

1

我花了一些时间来解决这个问题,并提出了几个解决方案。第一个基于 hadoop 流,第二个使用原生 java。

对于第一个解决方案,我使用了 ruby​​ 的一个有趣的特性。如果__END__在代码末尾添加关键字,则之后的所有文本都将由解释器通过全局变量 DATA 公开。这个变量是一个 File 对象。例子:

$ cat /tmp/foo.rb
puts DATA.read

__END__
Hello World!
$ ruby /tmp/foo.rb
Hello World!

我们将使用文件 R 作为输入(它将分布在 HDFS 文件系统中)。我们遍历 P 文件并在遍历一定数量的行之后,将它们添加到映射器脚本的末尾。然后,我们将作业提交到 hadoop 集群。我们不断迭代 P 的内容,直到我们用完所有行。多个作业将根据每个作业的行数和 P 的大小发送到集群。

这是我实施的一种很好的方法,而且效果很好。不过我觉得不是特别优雅。我们可以通过在 java 中编写本机 mapreduce 应用程序来做得更好。

使用本机 Java 应用程序时,我们可以完全访问 hadoop HDFS API。这意味着我们可以从代码中读取文件的内容。这是我认为流式传输时不可用的东西。

我们采用类似于流式方法的方法,但是一旦我们遍历了一定数量的行,我们就会将它们发送到 hadoop 集群,而不是将其附加到代码中。我们可以在安排工作的代码中做到这一点。

然后,运行与我们对 P 的拆分数量一样多的作业的问题。特定作业中的所有映射器将加载某个拆分并使用它来计算 R 的拆分。

于 2012-07-08T00:32:08.120 回答
0

好问题。

我能想到的一种快速方法是将 P 文件拆分为多个文件并运行多个 MR 作业,每次拆分 P 文件和完整的 R 文件作为输入。

于 2012-07-01T16:21:28.527 回答