我运行了一个Spark Streaming应用程序,它使用 mapWithState 函数来跟踪RDD的状态。 应用程序运行良好几分钟但随后崩溃
org.apache.spark.shuffle.MetadataFetchFailedException: Missing an output location for shuffle 373
我观察到,即使我已经为mapWithStateRDD设置了超时,Spark应用程序的内存使用也会随着时间线性增加。请参阅下面的代码段和内存使用情况 -
val completedSess = sessionLines
.mapWithState(StateSpec.function(trackStateFunction _)
.numPartitions(80)
.timeout(Minutes(5)))
如果每个RDD都有明确的超时,为什么内存会随时间线性增加?
我试过增加内存但没关系。我错过了什么?
编辑 - 参考代码
def trackStateFunction(batchTime:Time,key:String,value:Option [String],state:State [(Boolean,List [String],Long)]):Option [(Boolean,List [String])] = {
def updateSessions(newLine: String): Option[(Boolean, List[String])] = {
val currentTime = System.currentTimeMillis() / 1000
if (state.exists()) {
val newLines = state.get()._2 :+ newLine
//check if end of Session reached.
// if yes, remove the state and return. Else update the state
if (isEndOfSessionReached(value.getOrElse(""), state.get()._4)) {
state.remove()
Some(true, newLines)
}
else {
val newState = (false, newLines, currentTime)
state.update(newState)
Some(state.get()._1, state.get()._2)
}
}
else {
val newState = (false, List(value.get), currentTime)
state.update(newState)
Some(state.get()._1, state.get()._2)
}
}
value match {
case Some(newLine) => updateSessions(newLine)
case _ if state.isTimingOut() => Some(true, state.get()._2)
case _ => {
println("Not matched to any expression")
None
}
}
}
答案 0 :(得分:1)
根据mapwithstate的信息: 州规范 初始状态为RDD - 您可以从某个商店加载初始状态,然后以该状态启动流式传输作业。
分区数 - 键值状态dstream由键分区。如果您之前对状态的大小有一个很好的估计,则可以提供相应的分区数量。
分区程序 - 您还可以提供自定义分区程序。默认分区程序是散列分区程序。如果您对密钥空间有很好的理解,那么您可以提供一个自定义分区程序,它可以进行有效的更新,而不是默认的散列分区程序。
超时 - 这将确保在特定时间段内未更新其值的键将从状态中删除。这可以帮助用旧密钥清理状态。
因此,超时只与使用未更新的键一段时间后进行清理有关。内存将运行完全并最终阻塞,因为执行程序没有分配足够的内存。这给出了MetaDataFetchFailed异常。随着记忆的增加,我希望你的意思是执行者。即使这样,增加执行程序的内存也可能不起作用,因为流仍在继续。使用MapWithState,会话行将包含与输入dstream相同的记录数。所以解决这个问题就是让你的dstream更小。在流式上下文中,您可以设置批次间隔,这很可能会解决此问题
val ssc = new StreamingContext(sc,Seconds(batchIntervalSeconds))
请记住偶尔制作快照和检查点。快照将允许您使用现在较早丢失的流中的信息进行其他计算。希望这有助于获取更多信息,请参阅:https://docs.cloud.databricks.com/docs/spark/1.6/examples/Streaming%20mapWithState.html和http://asyncified.io/2016/07/31/exploring-stateful-streaming-with-apache-spark/
答案 1 :(得分:0)
mapWithState还将mappedValues存储在RAM中(参见MapWithStateRDD),默认情况下mapWithState存储在RAM中最多20个MapWithStateRDD。
简要说明RAM使用率与批处理间隔成正比,
您可以尝试减少批处理间隔以减少RAM使用量。