Hadoop小文件解决方案-Hadoop小文件的前因后果

28次阅读

共计 2255 个字符,预计需要花费 6 分钟才能阅读完成。

Hadoop 不适用于大量小文件,而是需要更少的大文件。这可能是您之前听过的声明。但是,为什么 Hadoop 会出现大量小文件的问题?而且,“小”究竟是什么意思呢?在本系列的第一部分中,我将回答这些问题。后续部分将讨论解决或解决小文件问题。
什么是小文件?

小文件可以定义为任何明显小于 Hadoop 块大小的文件。Hadoop 块大小通常设置为 64,128, 256 MB,越来越大。在本博客的其余部分提供示例时,我们将使用 128MB 的块大小。如果一个文件的大小不是块大小的 75%,那么它就是一个小文件。然而,小文件问题并不仅仅影响小文件。如果 Hadoop 集群中的大量文件稍微大于块大小的增量,那么您将遇到与小文件相同的挑战。
例如,如果您的块大小为 128MB,但加载到 Hadoop 的所有文件都是 136MB,那么您将拥有大量小的 8MB 块。好消息是解决小块问题就像选择合适的(较大的)块大小一样简单。解决小文件问题要复杂得多。注意我从来没有提到行数。虽然行数可以影响 MapReduce 性能,但在确定如何将文件写入 HDFS 时,它远不如文件大小重要。
为什么会出现小文件?

小文件问题是我们经常在 Hadoop 项目中看到的问题。公司可能在 Hadoop 中拥有小文件的原因有很多,包括:

公司越来越渴望能够实时获得数据,导致 Hadoop 摄取过程每小时 / 每周 / 每周运行,每个周期只生成 10MB 的新数据。
源系统生成数千个小文件,这些文件无需修改即可直接复制到 Hadoop 中。
MapReduce 作业的配置使用超过必要数量的 reducer,每个 reduceup 输出自己的文件。同样,如果数据中的偏差导致大部分数据转到一个减速器,那么剩余的减速器将处理非常少的数据并产生小的输出文件。

为什么 Hadoop 有一个小文件问题?

Hadoop 存在小文件问题有两个主要原因:NameNode 内存管理和 MapReduce 性能。namenode 内存问题 Hadoop 中的每个目录,文件和块都表示为 NameNode 内存中的对象。根据经验,每个对象需要 150 个字节的内存。如果你有 2000 万个文件,每个文件需要 1 个块,你的 NameNode 需要 6GB 的内存。这显然是非常可行的,但随着您的扩展,您最终会达到 NameNode 可以处理的文件(块)数量的实际限制。十亿个文件需要 300GB 的内存,并假设每个文件都在同一个文件夹中!让我们考虑 300GB NameNode 内存要求的影响 ……

当 NameNode 重新启动时,它必须从本地磁盘上的缓存中读取每个文件的元数据。这意味着从磁盘读取 300GB 的数据 – 可能会导致启动时间延迟。
在正常操作中,NameNode 必须不断跟踪并检查群集中每个数据块的存储位置。这是通过监听数据节点来报告其所有数据块来完成的。数据节点必须报告的块越多,它将消耗的网络带宽就越多。即使节点之间存在高速互连,这种规模的简单块报告也可能会造成破坏性。

优化很明显。如果可以减少群集中的小文件数,则可以减少 NameNode 内存占用,启动时间和网络影响。
MapReduce 的性能问题

拥有大量小文件会降低 MapReduce 处理的性能,无论是 Hive,Pig,Cascading,Pentaho MapReduce 还是 Java MapReduce。第一个原因是大量的小文件意味着大量的随机磁盘 IO。磁盘 IO 通常是 MapReduce 性能的最大限制因素之一。一次大的顺序读取总是胜过通过几次随机读取相同数量的数据。如果您可以将数据存储在更少,更大的块中,则可以减轻磁盘 IO 的性能影响。
性能下降的第二个原因有点复杂,需要了解 MapReduce 如何处理文件和调度资源。我将在此解释中使用 MapReduce 版本 1 术语,因为它比使用 Yarn 更容易解释,但相同的概念适用于 Yarn。当 MapReduce 作业启动时,它会为每个正在处理的数据块计划一个映射任务。存储在 Hadoop 中的每个文件至少有一个块。如果您有 10,000 个文件,每个文件包含 10 MB 的数据,则 MapReduce 作业将安排 10,000 个 map 任务。通常配置 Hadoop,以便每个 map 任务在其自己的 JVM 中运行。
您的 Hadoop 集群只有这么多资源。在 MapReduce v1 中,为避免节点过载,请指定节点可以处理的最大并发 map 数。通常,map 的最大数量在 5 到 20 范围内。因此,要同时运行 10,000 个 map,您必须拥有 500 到 2000 个节点。大多数 Hadoop 集群都小于此,导致 JobTracker 在等待打开的插槽时对 map 任务进行排队。如果您有一个包含总共 100 个插槽的 20 个节点群集,则您的队列将变得非常大,并且您的过程将花费很长时间。不要忘记,您的工作可能不是竞争集群资源的唯一工作。
如果您拥有 800 个 128 MB 的文件而不是 10,000 个 10MB 文件,那么您只需要 800 个 map 任务。这将需要一个数量级减少 JVM 维护时间,并将导致更好的磁盘 IO。即使处理 128 MB 的单个 map 任务将花费比处理 10 MB 的 map 任务处理更长的时间,但是当处理 800 个更大的文件时,所有处理时间的总和几乎总是要快几个数量级。
如果你有小文件,你会怎么做?

现在我们已经讨论了什么构成一个小文件以及为什么 Hadoop 更喜欢更大的文件,你如何避免小文件问题?在下一篇文章中,我将讨论 NameNode 内存问题的解决方案以及解决 MapReduce 性能问题的一些初始方案。在本系列一篇文章中,我将讨论性能问题的其他解决方案以及如何为您的情况选择最佳解决方案。

正文完
 0