Hadoop中数据是如何分割的

12

Hadoop是否基于程序中设置的映射器数量来切分数据?也就是说,如果有一个大小为500MB的数据集,如果映射器数为200(假设Hadoop集群同时允许200个映射器),则每个映射器会被分配2.5MB的数据吗?

此外,所有映射器是否都同时运行,还是有一些可能会串行运行?

5个回答

26
这反过来了。映射器的数量是基于拆分数来决定的。实际上,你正在使用的InputFormat应该创建这些拆分,因此在确定拆分数之前,你不知道映射器的数量。而且,并不总是基于HDFS块大小来创建拆分。这完全取决于getSplits()方法内部的逻辑。
例如,在处理存储在MySQL中的数据时,就没有块的概念,因此基于HDFS块创建拆分的理论将失败。那么,拆分是如何创建的呢?一个可能性是基于MySQL表中行的范围来创建拆分(这也是DBInputFormat所做的事情,一种从关系型数据库中读取数据的InputFormat)。比如说你有100行数据,那么你可能会有5个包含每个20行的拆分。
只有基于FileInputFormat(用于处理存储在文件中的数据)的InputFormats才会根据输入文件的总大小(以字节为单位)创建拆分。但是,输入文件的FileSystem块大小被视为输入拆分的上限。如果你有一个小于HDFS块大小的文件,你将只得到一个映射器。如果你想要一些不同的行为,你可以使用mapred.min.split.size。但这又完全取决于你的InputFormat中的getSplits()方法。
MR的split和HDFS的block之间有根本的区别,人们经常对此感到困惑。一个块是实际的数据块,而拆分只是将要提供给映射器的逻辑块。拆分不包含输入数据,它只是对数据的引用。那么什么是拆分呢?拆分基本上有两个东西:以字节为单位的长度和一组存储位置,这些位置只是主机名字符串。

回到您的问题。Hadoop允许使用超过200个mapper。话虽如此,对于只有500MB数据的情况下,拥有200个mapper并没有太多意义。请时刻记住,当涉及到Hadoop时,您处理的是非常庞大的数据。向每个mapper发送仅2.5MB的数据会导致过度运行。如果没有可用的CPU插槽,则某些mapper可能会在当前mapper完成后运行。但是MR框架非常智能,并尽力避免这种情况。如果需要处理的数据所在的机器没有任何可用的CPU插槽,则数据将转移到附近的有空闲插槽的节点进行处理。

希望对您有所帮助。


6
当你向Hadoop分布式文件系统(HDFS)输入数据时,Hadoop会根据块大小(默认为64 MB)拆分你的数据,并将块分布在集群中。因此,你的500 MB数据将被拆分成8个块。这不取决于mapper的数量,它是HDFS的属性。
现在,当你运行一个MapReduce作业时,默认情况下,Hadoop会为每个块分配1个mapper,因此如果你有8个块,则Hadoop将运行8个map任务。
然而,如果你明确指定了mapper的数量(即200个),那么每个Map处理的数据大小取决于块的分布,以及你的mapper在哪个节点上运行。实际处理你的数据的mapper数量取决于你的输入分割情况。
在你的情况下,假设500 MB分成8个块,即使你指定了200个mappers,即使它们初始化了,也不会全部处理数据。

谢谢。但是作业计数器显示有200个映射器已启动!你的意思是这不是真的吗? - HHH
1
在这种情况下,大多数映射器将运行但不会处理数据。当您检查映射器日志时,您会发现大部分映射器都没有输入/输出数据。我会编辑我的答案以反映这一点。 - Chaos

1
我刚刚根据你的问题运行了一个简单的MR程序,以下是我的发现:
输入:小于块大小的文件。
情况1:Mapper数量= 1 结果:启动了1个map任务。每个mapper(在这种情况下仅有一个)的Inputsplit大小与输入文件大小相同。
情况2:Mapper数量= 5 结果:启动了5个map任务。每个mapper的Inputsplit大小为输入文件大小的五分之一。
情况3:Mapper数量= 10 结果:启动了10个map任务。每个mapper的Inputsplit大小为输入文件大小的十分之一。
因此,对于小于块大小的文件,
拆分大小=总输入文件大小/启动的映射任务数。
注意:但请记住,map任务数量是基于输入拆分确定的。

此外,所有的映射器是否同时运行,还是有些可能会串行运行?-- 如果有足够的映射插槽,则所有映射任务将一起启动。如果您有比可用插槽更多的映射任务,则额外的映射任务将等待正在运行的映射器完成。 - Arijit Banerjee
请注意,我考虑到您正在使用旧的mapred API,因为我的代码是基于它的。这是FileInputFormat的getSplits签名,其中numSplits是一个参数。public InputSplit[] getSplits(JobConf job, int numSplits) - Arijit Banerjee
这是另一种方式。 - Tagar

0

不,这不是。

一项工作的映射器数量由框架定义。

请查看 Apache MapReduce 教程链接。

多少个映射?

映射数通常由输入数据的总大小(即输入文件块的总数)驱动。

映射的正确并行级别似乎在每个节点的10-100个映射之间,尽管已经为非常轻的 CPU 映射任务设置了高达300个映射。任务设置需要一段时间,因此最好让映射器执行时间至少为一分钟。

因此,如果您预计有 10TB 的输入数据,并且块大小为 128MB,则除非使用 Configuration.set(MRJobConfig.NUM_MAPS, int)(它仅向框架提供提示)将其设置得更高,否则您将获得 82,000 个映射。

回到您的查询:

假设Hadoop集群允许200个Mapper同时运行,那么如果数据集大小为500MB,每个Mapper是否会获得2.5MB的数据?
如果DFS块和输入分割大小为128MB,则500MB文件需要4个Mapper来处理数据。在上述情况下,框架将运行4个Mapper任务。
所有Mapper都同时运行吗?还是有些Mapper可能会按顺序运行?
所有Mapper都同时运行。但是只有当所有Mapper的输出已被复制并可用时,Reducer才会运行。

0
如果有200个映射器正在处理500MB的数据,则需要检查每个单独文件的大小。如果该文件大小小于块大小(64MB),则会为每个文件运行映射任务。
通常,我们将较小的文件合并成大文件(大小大于块大小)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接