我们在纱线上使用Spark 2.1.0进行多行记录的批处理。 我们的工作是用Pyspark编写的,每天运行一次。输入文件夹包含约45000个非常小的文件(每个文件的范围为1kB-100kB),总计约2GB。
每个文件包含不同数量的多行记录。记录的第一行具有标准模式,时间戳,后跟希腊µ和其他一些信息。例如:
28/09/2018 08:54:22µfirst record metadata
first record content with
undefined
number of
lines
28/09/2018 08:57:12µsecond record metadata
second record content
with a different
number of lines
这是我们读取数据框中的文件的方式:
df=spark.sparkContext.binaryFiles(input_path).toDF(['filename', 'content'])
raw = df.select('filename', explode(split(df.content, r'(?=\d{2}\/\d{2}\/\d{4} \d{2}:\d{2}:\d{2}µ)'))).cache()
第一行的输出是每个文件都有一个条目的数据框,第二行的输出是每个记录有一个条目的数据框。然后缓存数据帧并执行其他操作。
我们实际上正在测试解决方案,这是该工作的当前部署模式(但是内存需求过大):
spark2-submit --master yarn \
--conf spark.kryoserializer.buffer.max=1g \
--deploy-mode cluster \
--driver-memory 16g \
--driver-cores 1 \
--conf spark.yarn.driver.memoryOverhead=1g \
--num-executors 20 \
--executor-memory 16g \
--executor-cores 1 \
--conf spark.yarn.executor.memoryOverhead=1g \
spark_etl.py
该作业几乎每天都能正常运行,并且会在10到15分钟内执行所有操作,并将结果写入HDFS。
问题是,〜45000个输入文件中的一个文件每7-10天与另一个文件的大小完全不同:100MB到1GB(无论如何都小于2GB)。在这种情况下,我们的工作(特别是执行者之一)被挂起,似乎一直没有做任何事情。最初的几分钟后没有新的日志行。这需要几个小时,而且我们从未看到这些工作的结束,因为我们必须在几个小时之前将其杀死。我们怀疑这是由于“大”文件造成的,实际上,如果将其从输入文件夹中删除,则该作业运行良好。 这些是我们上次运行的截图:
Pyspark文档说明“首选小文件,也可以使用大文件,但可能会导致性能下降。我们可以接受性能下降的情况,但是我们认为情况并非如此,因为在我们看来,这项工作在整个过程中只是无所事事。
从Spark的角度来看,200MB的文件真的是“大文件”吗?如果是,我们如何改善工作绩效,或者至少了解它是否确实在做某事?
谢谢
答案 0 :(得分:0)
也许您应该提高执行者核心数。 binaryFiles创建BinaryFileRDD,然后BinaryFileRDD获取分区数取决于CPU处理器。
// setMinPartitions below will call FileInputFormat.listStatus(), which can be quite slow when
// traversing a large number of directories and files. Parallelize it.
conf.setIfUnset(FileInputFormat.LIST_STATUS_NUM_THREADS,
Runtime.getRuntime.availableProcessors().toString)