Scala Spark Streaming无法恢复挂起的批处理(TextFileStream)

Scala Spark Streaming无法恢复挂起的批处理(TextFileStream),scala,apache-spark,spark-streaming,Scala,Apache Spark,Spark Streaming,我使用Spark 2.3.1来处理文本文件流。上下文设置如下所示: val ssc=new StreamingContext(sparkSession.sparkContext, 秒(config.sparkStreamingBatchTime)) ssc.检查点(配置sparkCheckpointLocation) 除非没有足够的资源分配给作业,并且批开始堆积,否则一切正常。解决办法是终止工作,提供更多资源,然后重新开始 不幸的是,执行此操作时,已触发但尚未处理的挂起批次将丢失 示例:我每分

我使用Spark 2.3.1来处理文本文件流。上下文设置如下所示:

val ssc=new StreamingContext(sparkSession.sparkContext,
秒(config.sparkStreamingBatchTime))
ssc.检查点(配置sparkCheckpointLocation)
除非没有足够的资源分配给作业,并且批开始堆积,否则一切正常。解决办法是终止工作,提供更多资源,然后重新开始

不幸的是,执行此操作时,已触发但尚未处理的挂起批次将丢失

示例:我每分钟安排一次作业,只执行
线程.睡眠(3*60*1000)
(三分钟)。正如预期的那样,批次开始堆积

将为批处理引入一个新文件:

20/09/23 08:39:00 DEBUG FileInputDStream: Getting new files for time 1600850340000, ignoring files older than 1600850280000
20/09/23 08:39:00 DEBUG FileInputDStream: hdfs://nameservice1/[...]/test_1 accepted with mod time 1600850308293
20/09/23 08:39:00 INFO org.apache.spark.streaming.dstream.FileInputDStream: Finding new files took 18 ms
当文件集被持久化时,检查点系统可以正常工作:

20/09/23 08:39:00 DEBUG FileInputDStream: Updated checkpoint data for time 1600850340000 ms: [
3 file sets
1600850280000 ms ->
1600850340000 ms -> hdfs://nameservice1/[...]/test_1
1600850220000 ms ->
]
然后,我终止了该作业(显然是优雅的,因为调用了shudown钩子):

最后,当我再次启动作业时,由于文件的时间戳,该文件被忽略,但它最初没有被处理

20/09/23 08:44:00 DEBUG FileInputDStream: Getting new files for time 1600850640000, ignoring files older than 1600850580000
20/09/23 08:44:00 DEBUGFileInputDStream: hdfs://nameservice1/[...]/test_1 ignored as mod time 1600850308293 <= ignore time 1600850580000
20/09/23 08:44:00 INFO FileInputDStream: Finding new files took 3 ms
有了它,我至少可以记录哪些文件已被处理。然后,手动搜索未处理的。这很糟糕,但这是我唯一的解决办法

< P>更新第2版09/24/2020:我注意到我可以使用<代码> -CONFARCH.Studio.FielestRAM.MyReMeimeSimult使SCAP考虑旧的元数据文件,但是它不会阻止它重新处理已经处理过的文件。我需要使用上一次更新中的信息来删除这些文件,并强制管理员在启动作业之前清理旧的元数据文件

更新#3:09/30/2020 我已经深入研究了的源代码,对检查点的作用有了更好的了解。它恢复被监视目录的“快照”以及哪些文件在什么时候出现

然而,这里缺少的部分是,那些生成但从未处理过的“文件集”(即批处理),如何在重新启动作业后恢复它们

20/09/23 08:39:00 DEBUG FileInputDStream: Updated checkpoint data for time 1600850340000 ms: [
3 file sets
1600850280000 ms ->
1600850340000 ms -> hdfs://nameservice1/[...]/test_1
1600850220000 ms ->
]

不使用结构化流的原因是什么?不需要查看过去的数据或执行复杂的Spark SQL转换。该工具基本上对传入文件进行分组并合并它们(实际上,源文件夹是来自spark结构化流媒体作业的_spark_元数据文件夹)。我不考虑迁移,而是更喜欢使用检查点功能。对于每组文件,您是在执行窗口操作还是跨时间间隔更新状态的操作?或者您使用流式API是因为它能够检测更改?否,没有窗口或状态。只需要在批处理期间积累新文件,这样更改检测,正如您所说的,对我来说就足够了。度量和监控对我也很有用(以及错误恢复-如果有效的话)。您是否考虑过多个作业,即一个用于记录临时数据存储/队列中的文件更改,另一个用于处理该数据存储/队列中的更改,并在使用数据存储时标记已完成的更改。第一个作业的工作量较小,第二个作业总是可以通过检查其数据存储中是否有未完成处理的文件来重新启动。然后,您可以定期安排第二个任务,并根据每个作业的要求进行优化。不使用结构化流的原因是什么?无需查看过去的数据或执行复杂的Spark SQL转换。该工具基本上对传入文件进行分组并合并它们(实际上,源文件夹是来自spark结构化流媒体作业的_spark_元数据文件夹)。我不考虑迁移,而是更喜欢使用检查点功能。对于每组文件,您是在执行窗口操作还是跨时间间隔更新状态的操作?或者您使用流式API是因为它能够检测更改?否,没有窗口或状态。只需要在批处理期间积累新文件,这样更改检测,正如您所说的,对我来说就足够了。度量和监控对我也很有用(以及错误恢复-如果有效的话)。您是否考虑过多个作业,即一个用于记录临时数据存储/队列中的文件更改,另一个用于处理该数据存储/队列中的更改,并在使用数据存储时标记已完成的更改。第一个作业的工作量较小,第二个作业总是可以通过检查其数据存储中是否有未完成处理的文件来重新启动。然后,您可以定期安排第二个作业,并根据每个作业的要求进行优化。
20/09/23 08:39:00 DEBUG FileInputDStream: Updated checkpoint data for time 1600850340000 ms: [
3 file sets
1600850280000 ms ->
1600850340000 ms -> hdfs://nameservice1/[...]/test_1
1600850220000 ms ->
]