使用Spark将大量文件写入s3的最佳实践是什么

时间:2020-04-06 16:48:22

标签: apache-spark amazon-s3 hdfs

我正在尝试使用Spark将大约30k-60k的实木复合地板文件写入s3,由于s3速率限制,这需要大量时间(40+分钟)。 我想知道是否有最佳实践来做这样的事情。我听说将数据写入HDFS,然后使用s3-dist-cp复制可能更快。我不明白为什么。由于s3速率限制,不是从HDFS复制所需的时间相同吗?

感谢您的帮助

1 个答案:

答案 0 :(得分:0)

这种方法没有什么问题,并且在大多数用例中都可以正常工作,但是由于编写S3文件的方式可能会带来一些挑战。

需要理解的两个重要概念

  1. S3(对象存储)!= POSIX文件系统:重命名操作:

    基于POSIX的文件系统中的文件重命名过程是仅元数据操作。仅指针更改并且文件保留在磁盘上。例如,我有一个文件abc.txt,我想将其重命名为xyz.txt,它是瞬时的和原子的。 xyz.txt的最后修改时间戳与abc.txt的最后修改时间戳相同。 就像在AWS S3(对象存储)中一样,在后台重命名的文件是复制,然后是删除操作。首先将源文件复制到目标位置,然后再删除源文件。因此,“ aws s3 mv”更改目标文件的最后修改时间戳,这与POSIX文件系统不同。这里的元数据是一个键值存储,其中key是文件路径,而value是文件的内容,没有更改密钥并立即完成的过程。重命名过程取决于文件的大小。如果存在目录重命名(为简单起见,在S3中没有目录称为简化目录,我们可以假设将一组可恢复文件作为目录),则它取决于dir中文件的数量以及每个文件的大小。简而言之,与普通文件系统相比,S3中的重命名操作非常昂贵。

  2. S3一致性模型

    S3具有两种一致性a。写后读取b。最终一致性,在某些情况下会导致文件找不到期望的文件。文件未添加或未列出,文件已删除或未从列表中删除。

Deep explanation:

Spark利用Hadoop的“ FileOutputCommitter”实现来写入数据。再次写入数据涉及多个步骤,并在较高的阶段上暂存输出文件,然后提交它们,即写入最终文件。在这里,正如我之前所说的从暂存到最终步骤那样,涉及重命名步骤。如您所知,spark作业分为多个任务的阶段和集合,由于分布式计算的性质,任务容易失败,因此还提供了由于系统故障或推测性执行缓慢运行的任务而重新启动同一任务的条款,从而导致任务提交和作业的概念提交函数。这里有2种可供选择的可用算法,以及如何完成作业和任务提交,并且说这不是一种算法比其他算法更好,而是基于我们在哪里提交数据。

mapreduce.fileoutputcommitter.algorithm.version=1

  • commitTask将任务生成的数据从任务临时目录重命名为作业临时目录。

  • 所有任务完成后,commitJob将所有数据从作业临时目录重命名到最终目标,最后创建_SUCCESS文件。

这里的驱动程序最后完成commitJob的工作,因此由于大量任务临时文件排队等待重命名操作(虽然不是串行的)并且写入性能没有得到优化,所以像S3这样的对象存储可能需要更长的时间。对于HDFS来说,它可能工作得很好,因为重命名并不昂贵,并且只需更改元数据。对于AWS S3,在commitJob期间,文件的每个重命名操作都会打开对AWS S3的大量API调用,并且如果数量过多,可能会导致意外的API调用关闭文件很高。也可能不会。我已经看到同一工作的两个案例在两个不同的时间运行。

mapreduce.fileoutputcommitter.algorithm.version=2

  • commitTask在任务完成后立即将任务生成的数据从任务临时目录直接移动到最终目标。

  • commitJob基本上会写入_SUCCESS文件,并且不会执行太多操作。

从较高的角度看,它似乎已经过优化,但是它有一个局限性,即无法执行推测性任务,而且如果任何任务由于数据损坏而失败,那么我们最终可能会在最终目标中残留数据并需要清理。因此,这种算法无法提供100%的数据正确性,或者不适用于我们需要将数据以追加模式添加到现有文件的用例,即使这确保优化结果也存在风险。与算法1相比,重命名操作的次数更少(仍然有重命名)。在这里,我们可能会遇到文件未找到期望的问题,因为commitTask将文件写入临时路径并立即重命名它们,并且极有可能出现最终一致性问题。

最佳做法

我认为我们在编写Spark数据处理应用程序时可以使用的很少:

  • 如果您有可用的HDFS集群,则将数据从Spark写入HDFS并将其复制到S3以持久保存。 s3-dist-cp可以最佳地用于从HDFS到S3的数据复制。在这里,我们可以避免所有重命名操作。AWSEMR仅在计算期间运行,然后终止以保持结果,这种方法看起来更好。 p>

  • 尝试避免编写文件并一次又一次地读取它,除非有文件的使用者,并且spark在内存中处理方面众所周知,谨慎的数据持久性/缓存在内存中将有助于优化运行时间。该应用程序。

相关问题