【问题标题】:Azure DataBricks Stream foreach fails with NotSerializableExceptionAzure DataBricks Stream foreach 失败并出现 NotSerializableException
【发布时间】:2019-08-17 03:36:40
【问题描述】:

我想不断详细说明数据集流的行(最初由 Kafka 发起):根据我想更新 Radis 哈希的条件。这是我的代码 sn-p(lastContacts 是上一个命令的结果,它是这种类型的流:org.apache.spark.sql.DataFrame = [serialNumber: string, lastModified: long]。这扩展为 org.apache.spark.sql.Dataset[org.apache.spark.sql.Row]):

class MyStreamProcessor extends ForeachWriter[Row] {
  override def open(partitionId: Long, version: Long): Boolean = {
    true
  }

  override def process(record: Row) = {
    val stringHashRDD = sc.parallelize(Seq(("lastContact", record(1).toString)))
    sc.toRedisHASH(stringHashRDD, record(0).toString)(redisConfig)
  }

  override def close(errorOrNull: Throwable): Unit = {}
}

val query = lastContacts
  .writeStream
  .foreach(new MyStreamProcessor())
  .start()

query.awaitTermination()

我收到一个巨大的堆栈跟踪,相关部分(我认为)是这样的:java.io.NotSerializableException: org.apache.spark.sql.streaming.DataStreamWriter

谁能解释为什么会发生这种异常以及如何避免?谢谢!

这个问题与以下两个有关:

【问题讨论】:

    标签: apache-spark redis apache-kafka databricks azure-databricks


    【解决方案1】:

    Spark 上下文不可序列化。

    ForeachWriter 的任何实现都必须是可序列化的,因为每个任务都将获得所提供对象的新序列化反序列化副本。因此,强烈建议在调用 open(...) 方法之后进行任何写入数据的初始化(例如打开连接或启动事务),这表示任务已准备好生成数据。 em>

    在您的代码中,您尝试在流程方法中使用 spark 上下文,

    override def process(record: Row) = {
        val stringHashRDD = sc.parallelize(Seq(("lastContact", record(1).toString)))
        *sc.toRedisHASH(stringHashRDD, record(0).toString)(redisConfig)*
      }
    

    要向redis发送数据,需要自己创建连接,在open方法中打开,然后在process方法中使用。

    看看如何创建redis连接池。 https://github.com/RedisLabs/spark-redis/blob/master/src/main/scala/com/redislabs/provider/redis/ConnectionPool.scala

    【讨论】:

    • 感谢您的解释,很抱歉延迟了反应。因此,如果我理解正确,该解决方案实际上可以实现自己的 Redis 连接方法。这不是很好的解决方案;但是,您的回答回答了我的问题。
    猜你喜欢
    • 1970-01-01
    • 2022-01-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-12
    • 2019-08-15
    • 2020-04-10
    相关资源
    最近更新 更多