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性能问题的一些初始方案。在本系列一篇文章中,我将讨论性能问题的其他解决方案以及如何为您的情况选择最佳解决方案。