内存问题与火花结构流

时间:2018-03-11 00:08:04

标签: apache-spark apache-spark-sql spark-structured-streaming

我正面临在Spark 2.2.0中使用聚合和分区运行结构化流的内存问题:

session
    .readStream()
    .schema(inputSchema)
    .option(OPTION_KEY_DELIMITER, OPTION_VALUE_DELIMITER_TAB)
    .option(OPTION_KEY_QUOTE, OPTION_VALUE_QUOTATION_OFF)
    .csv("s3://test-bucket/input")
    .as(Encoders.bean(TestRecord.class))
    .flatMap(mf, Encoders.bean(TestRecord.class))
    .dropDuplicates("testId", "testName")
    .withColumn("year", functions.date_format(dataset.col("testTimestamp").cast(DataTypes.DateType), "YYYY"))
    .writeStream()
    .option("path", "s3://test-bucket/output")
    .option("checkpointLocation", "s3://test-bucket/checkpoint")
    .trigger(Trigger.ProcessingTime(60, TimeUnit.SECONDS))
    .partitionBy("year")
    .format("parquet")
    .outputMode(OutputMode.Append())
    .queryName("test-stream")
    .start();

在测试期间,我注意到每次新数据到来时最终使用的内存量都会增加,最后执行程序会以代码137退出:

ExecutorLostFailure (executor 2 exited caused by one of the running tasks) Reason: Container marked as failed: container_1520214726510_0001_01_000003 on host: ip-10-0-1-153.us-west-2.compute.internal. Exit status: 137. Diagnostics: Container killed on request. Exit code is 137
Container exited with a non-zero exit code 137
Killed by external signal

我创建了一个堆转储,发现org.apache.spark.sql.execution.streaming.state.HDFSBackedStateStoreProvider引用的package hello; import org.joda.time.LocalTime; public class HelloWorld { public static void main(String[] args) { LocalTime currentTime = new LocalTime(); System.out.println("The current local time is: " + currentTime); System.out.println("Hello World"); } } 使用的大部分内存

乍一看它看起来很正常,因为这就是Spark在内存中保存聚合键的方式。但是我通过重命名源文件夹中的文件来进行测试,以便可以通过spark获取它们。由于输入记录是相同的,因此所有进一步的行都应该被拒绝作为重复行,并且内存消耗不应该增加,但它应该是。

StateStore

此外,GC时间占总处理时间的30%以上

executor memory usage

这是从执行程序中获取的堆转储,其运行内存量小于上面的屏幕,因为当我从该进程创建转储时,java进程刚刚在进程中间终止。

enter image description here

2 个答案:

答案 0 :(得分:1)

迁移我对SPARK-23682的评论,该问题的提问者也已提出。

在HDFS状态存储提供程序中,它过多地将状态的多个版本缓存在内存中,默认为100个版本。 SPARK-24717解决了该问题,它将仅在内存中维护两个版本的状态(用于重放的当前版本,用于更新的新版本)。该补丁将在Spark 2.4.0中提供。

答案 1 :(得分:0)

我认为根本原因是您没有在dropDuplicates中使用水印,因此所有状态都将保留且永不丢弃。 看看:https://spark.apache.org/docs/latest/structured-streaming-programming-guide.html#streaming-deduplication