我试图了解当Spark在处理过程中出现异常时会发生什么,特别是在流式传输时。
如果我有一个像这样的小代码:
myDStream.foreachRDD { (rdd: RDD[String]) =>
println(s"processed => [${rdd.collect().toList}]")
throw new Exception("User exception...")
}
如果我运行这个,我会得到这样的输出:
[info] processed => [List(Item1)]
[error] 28-01-2016 17:41:18 ERROR JobScheduler:96 - Error running job streaming job 1453999278000 ms.0
[error] java.lang.Exception: User exception...
...
[info] processed => [List(Item2)]
[error] 28-01-2016 17:41:19 ERROR JobScheduler:96 - Error running job streaming job 1453999279000 ms.0
[error] java.lang.Exception: User exception...
首先处理“Item1”,然后失败(当然)。在下一批中处理“Item2”。记录“Item1”现已丢失。
如果我更改了我的代码,以便在任务中发生异常:
myDStream.foreachRDD { (rdd: RDD[String]) =>
println(s"processed => [${rdd.collect().toList}]")
rdd.map{case x => throw new Exception("User exception...") }.collect()
}
然后将重试地图闭包,但是一旦失败了足够的次数,记录就会被丢弃,处理继续到下一个记录。
是否可以确保不丢弃记录,即使这意味着停止应用程序?我启用了WAL。
更新:Tathagata Das在Spark用户邮件列表here上回复。
答案 0 :(得分:0)
假设您已将PreparedStatement
配置为spark.streaming.receiver.writeAheadLog.enable
,还建议在您的Spark作业中创建Stream时使用true
作为MEMORY_AND_DISK_SER_2
,这将确保您的数据在进一步处理之前复制。
我假设您在流式传输作业中也需要StorageLevel
语义,为此您还需要检查并确保您的接收器可靠。
还建议推荐 this 部分来执行交易更新。
最后还建议部署一些监视工具,用于监视/检查Executor日志中是否存在任何异常,以及何时遇到查杀或采取适当措施。