共计 2673 个字符,预计需要花费 7 分钟才能阅读完成。
通过研究一些不太常用的替代方案来解决 MapReduce 性能问题以及选择解决方案时要考虑的因素。
解决 MapReduce 性能问题
以下解决方案来缓解 MapReduce 性能问题:
更改摄取过程 / 间隔
批处理文件合并
序列文件
HBase
S3DistCp(如果使用 Amazon EMR)
使用 CombineFileInputFormat
Hive 配置
使用 Hadoop 的附加功能
已经讨论过更改摄取过程,批处理文件合并和序列文件。
Hbase
如果要生成大量小文件,将数据作为文件存储在 HDFS 中可能不是最佳解决方案。相反,您可以考虑使用 HBase 列存储。使用 HBase 可以将摄取过程从生成许多小型 HDFS 文件更改为将单个记录写入 HBase 表。如果您的数据访问模式基于明确定义的随机访问查找,则 HBase 可能是您的最佳选择。它在架构上针对高速数据记录插入,大容量,单个记录查找和基于流的分析进行了调整。但是,如果您的数据访问模式倾向于完整文件 / 表扫描,那么 HBase 可能不是最佳的。
可以创建映射到 HBase 数据的 Hive 表; 但是,此设计中的查询性能会有所不同。当选择单行或一系列行时,HBase 上的 Hive 会闪烁,但如果您的查询倾向于全表扫描,则 HBase 的效率非常低。大多数分析查询,尤其是那些使用 group by 的查询,都需要进行全表扫描。
HBase 提供了将数据流式传输到 Hadoop 并使其可实时处理的最佳能力。但是,平衡 HBase 与其他集群进程的需求可能具有挑战性,并且需要高级系统管理。此外,HBase 性能在很大程度上取决于数据访问模式,在选择 HBase 解决小文件问题之前,应仔细考虑这些模式。
S3DistCp
此解决方案仅适用于 Amazon EMR 的用户。Amazon EMR 集群的生命周期很短,将数据保存在 Amazon S3 中。即使使用 Amazon S3,处理大量小文件仍然会导致启动不必要的 map 任务,从而降低性能。
S3DistCp 是亚马逊提供的一种实用程序,用于将数据从 S3 分发复制到临时 HDFS 甚至其他 S3 存储桶。该实用程序提供了通过使用 groupBy 和 targetSize 选项将文件连接在一起的功能。当您在 S3 中存储了数千个要使用 Amazon EMR 处理的小文件时,这非常有用。S3DistCp 通过连接许多小文件并使它们出现在更快,短暂的 HDFS 存储中,一举两得。据报道,使用这种机制可以提高 15 倍的性能。
出于所有实际目的,S3DistCp 执行与提到的批处理文件合并方法相同的任务。如果使用 Amazon EMR,请注意您有一个预先构建的工具来完成此任务。
使用 CombineFileInputFormat
CombineFileInputFormat 是 Hadoop 提供的抽象类,它在 MapReduce 读取时合并小文件。合并的文件不会持久保存到磁盘。相反,该过程读取多个文件并“动态”合并它们以供单个 map 任务使用。您可以获得不为每个文件启动一个 map 任务的好处,并且不需要将多个文件合并到一个持久文件中作为准备步骤的一部分。这解决了 MapReduce 作业启动太多 map 任务的问题; 但是,由于作业仍在读取多个小文件,因此随机磁盘 IO 仍然存在问题。此外,CombineFileInputFormat 的大多数实现都不考虑数据局部性,并且通常会通过网络从各种数据节点提取数据。
为了实现这一点,必须在 Java 中为不同的文件类型扩展 CombineFileInputFormat。这需要大量的开发专业知识来开发您的自定义输入格式类。但是,一旦编写,您可以配置最大分割大小,它将合并文件,直到满足此大小。
请注意,由于合并数据不会在 HDFS 中保留,因此 CombineFileInputFormat 不会缓解 NameNode 内存问题。
Hive 配置
如果您注意到 Hive 通过“create table as”或“insert overwrite”语句在 Hadoop 集群中创建小文件,则可以调整一些 Hive 特定配置设置以进行缓解。使用时,这些设置会告诉 Hive 将创建的任何小文件合并到较大的文件中。但是,有一个惩罚。Hive 将启动一个额外的 MapReduce 作业后查询,以执行合并。此外,在 Hive 向用户指示查询已完成处理而不是异步发生之前完成合并。
应该注意,这些设置仅适用于由 Hive 创建的文件。例如,如果使用其他工具(如 Sqoop)在 Hive 外部创建文件,则使用 hdfs fs -mv 命令将其复制到 Hive 表中,Hive 将不会合并文件。因此,当摄入 Hadoop 的文件很小时,此解决方案不起作用。此解决方案仅建议在以 Hive 为中心的体系结构中,其中 insert overwrite 和 create table as 语句中的小性能损失是可接受的。
要使用的设置是:
使用 Hadoop 的附加功能
附加可能是可用的,但 Hadoop 生态系统中的主要工具都不支持它:Flume,Sqoop,Pig,Hive,Spark 和 Java MapReduce。MapReduce 强制执行一条规则,即 MapReduce 作业的输出位置在执行之前不得存在。由于这个规则,MapReduce 显然不可能通过其输出附加到预先存在的文件。由于 Sqoop,Pig 和 Hive 都使用了 MapReduce,因此这些工具也不可能支持追加。Flume 不支持追加很大程度上是因为它假设经过一段时间(无论是秒,字节,事件数或不活动秒),Flume 将关闭文件而不再打开它。Flume 社区认为这足够,而不是要求追加支持。
如果你真的必须在 Hadoop 中使用 appends,你必须编写自己的系统来执行摄取并附加到现有文件。此外,如果您的任何群集内处理需要附加到现有文件,您将无法使用 Spark 或 MapReduce。因此,使用 HDFS 附加功能非常复杂,只能由技术最精湛的组织使用。如果没有重要的工程团队和支持承诺,则不建议使用此选项。
选择解决方案
选择使用小文件的最佳解决方案取决于各种问题。可能有必要根据访问模式和数据要求使用这些解决方案的组合。应该考虑的问题包括:
数据流中的哪一点是生成的小文件?是在摄取时还是通过群集内处理创建小文件?
生成小文件的工具是什么?更改工具配置可以减少小文件的数量吗?
您的组织有多少技术技能?您是否有能力维护输入格式或编写自己的摄取引擎?
生成小文件的频率是多少?为了创建大文件,可以多久合并一次小文件?
这些小文件需要哪种数据访问?这些文件是否需要通过 Hive 访问?
可以在集群内部运行流程以减轻小文件的管理周期类型?
MapReduce 流程可接受的延迟级别是多少?