【发布时间】:2019-03-08 19:17:04
【问题描述】:
我们在 Yarn 上使用 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
这就是我们在 Dataframe 中读取文件的方式:
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。
问题是,每 7 到 10 天,大约 45000 个输入文件中的一个与其他文件相比具有完全不同的大小:100MB 到 1GB(无论如何小于 2GB)。在这种情况下,我们的工作(特别是执行者之一)挂起并且似乎一直没有做任何事情。第一分钟后没有新的日志行。这需要几个小时,我们从来没有看到这些工作的结束,因为我们必须在几个小时之前杀死它们。我们怀疑这是因为“大”文件,事实上,如果我们从输入文件夹中删除它,作业运行良好。 这些是我们上次运行的截图:
Pyspark 文档说明“首选小文件,也允许使用大文件,但可能会导致性能不佳。”。我们可以接受性能恶化,但我们认为情况并非如此,因为在我们看来,这项工作在整个过程中只是无所事事。
从 Spark 的角度来看,一个 200MB 的文件真的是“大文件”吗?如果是,我们如何才能提高工作绩效,或者至少了解它是否真的在做某事?
谢谢
【问题讨论】:
标签: apache-spark pyspark apache-spark-sql