Apache spark 如何在结构化流媒体中正确使用foreachBatch.batchDF.unpersist()?(有个错误)
我正在使用Spark 3.0的结构化流媒体 我要做的是将数据写入多个接收器。我需要在Kafka中编写一些数据帧,以便在另一个进程中使用,还需要在Cassandra中存储相同的数据帧,以供以后使用(一些仪表板等) 对于目标过程,我编写了如下代码。我参考了来自中国的官方文件 但是,每当我在foreachBatch的最后一部分中写入Apache spark 如何在结构化流媒体中正确使用foreachBatch.batchDF.unpersist()?(有个错误),apache-spark,caching,compiler-errors,spark-structured-streaming,Apache Spark,Caching,Compiler Errors,Spark Structured Streaming,我正在使用Spark 3.0的结构化流媒体 我要做的是将数据写入多个接收器。我需要在Kafka中编写一些数据帧,以便在另一个进程中使用,还需要在Cassandra中存储相同的数据帧,以供以后使用(一些仪表板等) 对于目标过程,我编写了如下代码。我参考了来自中国的官方文件 但是,每当我在foreachBatch的最后一部分中写入batchDF.unpersist()时,就会出现编译错误: [error] (function: org.apache.spark.api.java.function
batchDF.unpersist()
时,就会出现编译错误:
[error] (function: org.apache.spark.api.java.function.VoidFunction2[org.apache.spark.sql.Dataset[org.apache.spark.sql.Row],java.lang.Long])org.apache.spark.sql.streaming.DataStreamWriter[org.apache.spark.sql.Row] <and>
[error] (function: (org.apache.spark.sql.Dataset[org.apache.spark.sql.Row], scala.Long) => Unit)org.apache.spark.sql.streaming.DataStreamWriter[org.apache.spark.sql.Row]
[error] cannot be applied to ((org.apache.spark.sql.DataFrame, scala.Long) => org.apache.spark.sql.DataFrame)
[error] .foreachBatch({(batchDF: DataFrame, batchId: Long) => {
[error] ^
[error] one error found
[error] (Compile / compileIncremental) Compilation failed
[error](函数:org.apache.spark.api.java.function.VoidFunction2[org.apache.spark.sql.Dataset[org.apache.spark.sql.Row],java.lang.Long])org.apache.spark.sql.streamwriter[org.apache.spark.sql.Row]
[错误](函数:(org.apache.spark.sql.Dataset[org.apache.spark.sql.Row],scala.Long)=>Unit)org.apache.spark.sql.streaming.DataStreamWriter[org.apache.spark.sql.Row]
[错误]无法应用于((org.apache.spark.sql.DataFrame,scala.Long)=>org.apache.spark.sql.DataFrame)
[错误].foreachBatch({(batchDF:DataFrame,batchId:Long)=>{
[错误]^
[错误]发现一个错误
[错误](编译/编译增量)编译失败
当我删除batchDF.unpersist()
时,它工作正常,并且我检查了数据是否能很好地进入Kafka和Cassandra。但是,很明显,它很快就出现了内存不足错误,因为缓存的数据仍保留在内存中
我还尝试使用sparkSession.catalog.clearCache()
,但它似乎没有按我的预期工作
为什么会发生此错误,因为我的代码与文档完全相同?另外,如何修复它
提前感谢。Spark为Scala和Java提供了两种不同的方法,因为Scala在Scala 2.12之前不生成Java lambda
/**
* Applies a function `f` to all rows.
*
* @group action
* @since 1.6.0
*/
def foreach(f: T => Unit): Unit = withNewRDDExecutionId {
rdd.foreach(f)
}
/**
* (Java-specific)
* Runs `func` on each element of this Dataset.
*
* @group action
* @since 1.6.0
*/
def foreach(func: ForeachFunction[T]): Unit = foreach(func.call(_))
这是为了方便Java用户,但一旦Spark开始支持Scala 2.12,这些方法就会相互冲突
Spark社区中进行了相关讨论,但似乎做出了保持API兼容性的决定。不幸的是,您需要“严格”匹配两个方法之间的签名之一,例如,在lambda的末尾添加
Unit
。根据错误消息和几次实验猜测,我确认当foreachBatch
中的函数以batchDF.unpersist()结尾时,代码出现编译错误
。所以我只是在函数末尾使用无意义的逻辑来避免编译错误(例如if(false){}
),但我仍然不知道为什么会发生这种情况..这是scala问题,因为方法中的最后一行是该方法的返回值。因此编译的签名与预期的签名不匹配。尝试将foreachBatch
中的所有函数代码提取到一个声明返回Unit
的方法中,然后这会解决你的问题。
/**
* Applies a function `f` to all rows.
*
* @group action
* @since 1.6.0
*/
def foreach(f: T => Unit): Unit = withNewRDDExecutionId {
rdd.foreach(f)
}
/**
* (Java-specific)
* Runs `func` on each element of this Dataset.
*
* @group action
* @since 1.6.0
*/
def foreach(func: ForeachFunction[T]): Unit = foreach(func.call(_))