S3中有大约15000个文件(ORC),每个文件包含几分钟的数据,每个文件的大小在300-700MB之间。
由于递归循环以YYYY / MM / DD / HH24 / MIN格式存在的目录很昂贵,我创建的文件包含给定日期的所有S3文件列表(objects_list.txt)并将此文件作为输入到spark read API
$file = $basepath . $filename;
$content = file_get_contents($file);
// do whatever you want to the content
$newfile = $basepath . $newfilename;
file_put_contents($newfile, $content);
群集的大小是10 r3.4xlarge机器(工作者)(其中每个节点:120GB RAM和16个核心)和master是m3.2xlarge配置(
面临的问题是,火花读取无休止地运行,我看到只有驱动程序工作和休息所有节点都没有做任何事情并且不确定为什么驱动程序打开每个S3文件进行读取,因为AFAIK spark工作懒惰所以直到一个动作被称为阅读不应该发生,我认为它列出了每个文件并收集了与之相关的一些元数据。
但是为什么只有Driver工作并且休息所有节点都没有做任何事情,我怎样才能让这个操作在所有工作节点上并行运行?
我遇到过这些文章https://tech.kinja.com/how-not-to-pull-from-s3-using-apache-spark-1704509219和https://gist.github.com/snowindy/d438cb5256f9331f5eec,但这里整个文件内容都被读取为RDD,但我的用例取决于只引用那些块/列的列应该从S3获取数据(给定ORC的列式访问是我的存储)。 S3中的文件大约有130列,但只使用数据框API的
引用和处理了20个字段val file_list = scala.io.Source.fromInputStream(getClass.getResourceAsStream("/objects_list.txt"))
val paths: mutable.Set[String] = mutable.Set[String]()
for (line <- file_list.getLines()) {
if(line.length > 0 && line.contains("part"))
paths.add(line.trim)
}
val eventsDF = spark.read.format("orc").option("spark.sql.orc.filterPushdown","true").load(paths.toSeq: _*)
eventsDF.createOrReplaceTempView("events")
您可以在下面看到,只有一个Executor正在其中一个任务节点(集群模式)上运行该驱动程序,其余的其他节点(即工作人员)上的CPU为0%,甚至在3-4小时之后处理时,情况相同,因为必须处理大量文件
有关如何避免此问题的任何指针,即加快加载和处理?
答案 0 :(得分:4)
有一种解决方案可以帮助您使用AWS Glue。
您的S3中有很多文件已分区。但是你有基于时间戳的分区。因此,使用胶水,您可以在S3中使用您的对象,例如&#34; hive tables&#34;在您的EMR中。
首先,您需要创建版本为5.8+的EMR,您将能够看到:
您可以设置此检查两个选项。这将允许访问AWS Glue数据目录。
在此之后,您需要将根文件夹添加到AWS Glue目录中。快速的方法是使用Glue Crawler。此工具将抓取您的数据并根据需要创建目录。
我建议你看看here。
抓取工具运行后,您将在目录中获得表格的元数据,您可以在AWS Athena看到。
在Athena中,您可以检查抓取工具是否正确识别了您的数据。
此解决方案将使您的火花接近真正的HDFS。由于元数据将在数据目录中正确显示。而你的应用程序正在寻找&#34;索引&#34;将允许更快地运行作业。
在这里使用它我能够改进查询,使用胶水处理分区效果要好得多。所以,试一试这可能对性能有所帮助。