【问题标题】:HDFS performance for small files小文件的 HDFS 性能
【发布时间】:2012-12-21 15:50:15
【问题描述】:

我是 Hadoop 新手。最近我正在尝试处理(只读)hdfs/hadoop 上的许多 small 文件。平均文件大小约为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/秒

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

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

这是我的一些配置:

NameNode 堆大小 32G。

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

NameNode 处理程序计数:128

DataNode 处理程序计数:8

DataNode最大传输线程数:4096

1GBps 以太网。

谢谢。

【问题讨论】:

  • 补充:程序从标准输入读取一个文件列表,其中包含数百万个文件路径。
  • 我总是忘记“为什么”和“如何”,但请尝试使您的输入文件至少与块大小一样大(默认为 64 MB),然后重新运行您的分析。合并文件的方式取决于它们的格式;如果它们只是文本,你可以将它们连接起来。
  • 我知道将文件合并成更大的文件可以显着提高性能,但这不是我们的首选。顺便说一句,直接从磁盘读取文件也会有很大的改进。我真的很想知道与本机访问相比,HDFS 可以提供的合理吞吐量是多少。 1/7 似乎不太好。

标签: performance hadoop io hdfs


【解决方案1】:

HDFS 确实不是为许多小文件设计的。

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

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

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

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

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

【讨论】:

  • 我正在考虑合并小文件。但正常我不需要阅读所有这些。例如,我有 100M 的文件,但我只需要读取 30M 的文件。序列文件可以为此工作吗?由于我需要将数据加载到 C++ 程序中,我将使用 hadoop 流。在这种情况下序列文件可以工作吗?我有更好的选择吗? BTW,我的场景是我已经有100M的文件了,每天会增加10s个文件,每天删除不到100个文件,文件不会被修改。
  • 我同意乔的意见,我应该将小文件合并成更大的文件。看起来我应该弄清楚如何使用 hadoop 流来做到这一点。并找出序列文件或 HAR 是否能满足我的要求。
【解决方案2】:

只是补充一下 Joe 所说的,HDFS 和其他文件系统之间的另一个区别是,与传统的 FS 相比,它通过将数据存储在更大的块(通常为 64M 或 128M)中来尽可能少地减少磁盘 I/O。块大小以 KB 为单位。出于这个原因,他们总是说 HDFS 擅长处理少量大文件,而不是处理大量小文件。这背后的原因是,尽管最近在 cpu、ram 等组件方面取得了显着进步,但磁盘 i/o 是一个我们仍然没有太大进步的领域。这就是拥有如此巨大的块(与传统的 FS 不同)并尽可能减少磁盘使用的目的。

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

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

【讨论】:

  • 您好,我很抱歉像这样闯入,但您能否告诉我是否可以使用 hadoop 为流量很大的网站提供图片?将许多小文件合并为一个大文件(序列文件)是否会使其访问速度变慢。非常感谢。
  • 欢迎您@qualebs..这听起来不是一个非常可行的想法。 Hadoop 本身(特别是 HDFS)与任何其他 FS 一样,不适合需要实时访问存储数据的用例,例如用户发布查询并期望即时响应的网站。
  • 以分布式方式(即无限空间)存储这些小文件有哪些替代方案?还可以快速访问?
【解决方案3】:

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

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

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

【讨论】:

  • 我能有更好的namenode性能的原因是因为我使用了更好的硬件。戴尔 R620,2 个 E5-2650 CPU(包括超线程在内共 32 个内核),128GB RAM。
  • 我认为我没有达到 1GB 以太网的限制,因为总吞吐量是由 5 台机器实现的。 5 个数据节点通过 1GB 的双向网络交换机连接。由于交换机和everynet 适配器都是全双工的,我应该为5 台机器获得至少2.5GB 的带宽。
  • 所以我认为你从 Datanode 设置文件传输的开销中遇到了瓶颈(或者实际上是 NameNode 瓶颈
  • @DavidGruzman :增加编号是否有益? dfs.datanode.max.xcievers 和 dfs.namenode.handler.count,因为 NN 看起来很强大??
  • 它将增加datanode可以处理的并发性。同时 - 它不会减少每个文件的读取开销。同时-我会认真考虑例如 HBASE 或其他适合小数据块的解决方案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-11-27
相关资源
最近更新 更多