为啥在 EMR 5.x 版本中取消了对 Amazon S3 的直接写入?

Posted

技术标签:

【中文标题】为啥在 EMR 5.x 版本中取消了对 Amazon S3 的直接写入?【英文标题】:Why are direct writes to Amazon S3 eliminated in EMR 5.x versions?为什么在 EMR 5.x 版本中取消了对 Amazon S3 的直接写入? 【发布时间】:2017-03-21 10:30:34 【问题描述】:

阅读本页后:

http://docs.aws.amazon.com/emr/latest/ReleaseGuide/emr-hive-differences.html “操作差异和注意事项”->“消除了直接写入 Amazon S3”部分。

我想知道 - 这是否意味着在 EMR 4.x 版本中从 Hive 写入 S3 会比 5.x 版本更快? 如果是这样,这不是一种回归吗? AWS 为什么要取消这种优化? 写入位于 S3 中的 Hive 表是一种非常常见的场景。

有人可以解决这个问题吗?

【问题讨论】:

【参考方案1】:

此优化最初由 Qubole 开发并推送到 Apache Hive。 见here。

此功能相当危险,因为它绕过了 Hive 容错机制,并且还迫使开发人员使用通常不必要的中间表,这反过来又会导致性能下降并增加成本。

非常常见的用例是当我们需要将增量数据合并到分区目标表中时,描述为here 查询是从自身插入覆盖表,没有中间表(在单个查询中)它是相当有效的。查询可能要复杂得多,连接了许多表。这是在此用例中启用直接写入时会发生的情况:

    分区文件夹在查询完成之前被删除,这导致 Mapper 读取正在写入的同一个表时出现 FileNotFound 异常,因为分区文件夹在映射器执行之前被删除。

    如果目标表最初为空,则首次运行成功,因为 Hive 知道没有任何分区并且不读取文件夹。第二次运行失败,因为在映射器完成之前看到 (1) 文件夹已删除。

    已知的解决方法会影响性能。以增量方式加载数据通常是用例。在这种情况下,直接写入 S3 功能会迫使开发人员使用临时表来消除 FileNotFoundException 和表损坏。因此,与禁用此功能并从自身写入目标表相比,我们执行此任务的速度要慢得多,成本也要高得多。

    第一次失败后,无法成功重启,表不可选择不可写,因为元数据中存在 Hive 分区但文件夹不存在,这导致该表的其他查询中出现 FileNotFoundException,这些查询没有覆盖它。

您所指的亚马逊页面上的描述相同,但细节较少:https://docs.aws.amazon.com/emr/latest/ReleaseGuide/emr-hive-differences.html

Qubole page 描述了另一个可能的问题,提到了一些使用前缀的现有修复,尽管这不适用于上述用例,因为将新文件写入正在读取的文件夹中无论如何都会产生问题。

此外,映射器、reducer 可能会失败并重新启动,整个会话可能会失败并重新启动,即使推迟删除旧文件也直接写入文件似乎不是一个好主意,因为它会增加不可恢复的失败或数据损坏的机会。

要禁用直接写入,请设置此配置属性:

set hive.allow.move.on.s3=true; --this disables direct write

您可以将此功能用于小任务,并且当不读取正在写入的同一张表时,尽管对于小任务它不会给您太多。当您在一个非常大的表中重写许多分区并且最后移动任务非常慢时,这种优化最有效,那么您可能希望启用它以冒数据损坏的风险。

【讨论】:

以上是关于为啥在 EMR 5.x 版本中取消了对 Amazon S3 的直接写入?的主要内容,如果未能解决你的问题,请参考以下文章

mrjob 在 Amazon EMR 5.x 上不起作用,但在 EMR4.8.3 上运行

当我在 pyspark EMR 5.x 中运行用 Java 编写的 hive UDF 时出错

为啥我们在启用 Kerberos 的 EMR 集群上使用直线连接到 Hive 时使用 Hive 服务主体?

Svn 1.5.x 与最新版本

为啥 AWS EMR 上的 Spark 不从应用程序 fat jar 加载类?

为啥任务取消发生在调用者线程上?