7

我是 Hadoop 新手。最近我正在尝试处理(只读)hdfs/hadoop 上的许多小文件。平均文件大小约为1 kb,文件数超过10M。由于某些限制,该程序必须用 C++ 编写。

这只是一个性能评估,所以我只使用 5 台机器作为数据节点。每个数据节点有5个数据盘。

我编写了一个小型C++ 项目来直接从硬盘(而不是 HDFS)读取文件来构建性能基准线。该程序将为每个磁盘创建 4 个读取线程。性能结果是每个磁盘大约 14MB/s。总吞吐量约为 14MB/s * 5 * 5 = 350MB/s( 14MB /s * 5 个磁盘 * 5 台机器)。

但是,当这个程序(仍然使用 C++,动态链接 libhdfs.so,创建 4*5*5=100 个线程)从 hdfs 集群中读取文件时,吞吐量只有55MB/s左右。

如果这个编程在 mapreduce 中触发(hadoop 流式处理,5 个作业,每个有 20 个线程,线程总数仍然是 100),吞吐量下降到大约 45MB/s。(我想它会因一些簿记过程而减慢)。

我想知道 HDFS 可以提供的合理性能是什么。如您所见,与原生代码相比,数据吞吐量仅为1/7左右。是我配置的问题吗?还是 HDFS 限制?还是Java限制?我的方案的最佳方式是什么?序列文件有帮助(很多)吗?与我们可以预期的原生 IO 读取相比,合理的吞吐量是多少?

这是我的一些配置:

NameNode 堆大小 32G。

作业/任务节点堆大小 8G。

NameNode 处理程序计数:128

数据节点处理程序计数:8

DataNode最大传输线程数:4096

1GBps 以太网。

谢谢。

4

3 回答 3

8

HDFS 真的不是为许多小文件而设计的。

对于您读取的每个新文件,客户端必须与 namenode 对话,namenode 会为其提供文件块的位置,然后客户端从 datanode 流式传输数据。

现在,在最好的情况下,客户端这样做一次,然后发现它上面有数据的机器,并且可以直接从磁盘读取它。这将很快:与直接磁盘读取相当。

如果不是机器上有数据,那么它必须通过网络传输数据。然后你会受到网络 I/O 速度的限制,这应该不会很糟糕,但仍然比直接读取磁盘要慢一些。

但是,您会遇到更糟糕的情况——与名称节点通信的开销变得很大。只需 1KB 的文件,您就可以交换与实际数据一样多的元数据。客户端必须进行两次单独的网络交换才能从每个文件中获取数据。除此之外,namenode 可能会受到所有这些不同线程的影响,因此它可能会成为瓶颈。

因此,要回答您的问题,是的,如果您将 HDFS 用于并非设计用于的用途,那么它会很慢。合并您的小文件,并使用 MapReduce 获取数据局部性,您将获得更好的性能。事实上,因为您将能够更好地利用顺序磁盘读取,所以如果从一个大 HDFS 文件读取比读取许多本地小文件更快,我不会感到惊讶。

于 2012-12-21T18:29:48.790 回答
3

补充一下 Joe 所说的,HDFS 和其他文件系统之间的另一个区别是,与 FS 块大小为以 KB 为顺序。出于这个原因,他们总是说 HDFS 擅长处理少量大文件,而不是处理大量小文件。这背后的原因是,尽管最近在 cpu、ram 等组件方面取得了显着进步,但磁盘 i/o 是一个我们仍然没有太大进步的领域。这是拥有如此巨大的块(与传统的 FS 不同)并尽可能减少磁盘使用的目的。

此外,如果块大小太小,我们将拥有更大的块数。这意味着更多的元数据。这可能会再次降低性能,因为需要将更多信息加载到内存中。对于每个被认为是 HDFS 中的对象的块,都有大约 200B 的元数据与之关联。如果你有很多小块,它只会增加元数据,你最终可能会遇到 RAM 问题。

Cloudera 的博客部分有一篇非常好的文章,它讨论了同样的问题。你可以在这里访问。

于 2012-12-21T19:21:04.720 回答
1

让我们尝试了解我们的限制,看看我们何时达到了它们
a) 我们需要 namenode 来为我们提供文件所在位置的信息。我可以假设这个数字大约是每秒数千。更多信息在这里https://issues.apache.org/jira/browse/HADOOP-2149 假设这个数字是 10000K,我们应该能够获得关于 1K 文件的 10 MB 秒的信息。(不知何故你得到更多......)。可能
b) HDFS 的开销。这种开销主要是延迟而不是吞吐量。HDFS 可以调整为以并行方式提供大量文件。HBase 正在这样做,我们可以从 HBase 调优指南中获取设置。这里的问题实际上是您需要多少 Datanodes
c) 您的 LAN。您从网络移动数据,因此您可能会达到 1GB 以太网吞吐量限制。(我认为这是你得到的。

我也必须同意 Joe 的观点——HDFS 不是为这个场景而构建的,你应该使用其他技术(比如 HBase,如果你喜欢 Hadoop 堆栈)或者将文件压缩在一起——例如压缩成序列文件。

关于从 HDFS 读取更大的文件 - 运行 DFSIO 基准测试,这将是你的数字。
同时 - 单主机上的 SSD 也可以是一个完美的解决方案。

于 2012-12-23T11:19:21.730 回答