在何处定义要在Spark Java中广播的对象

在何处定义要在Spark Java中广播的对象,java,apache-spark,Java,Apache Spark,我有一个数据库对象,用于插入来自所有Spark执行器的数据。当我将这个对象定义为static时,这些执行器中有一个null值。所以我在驱动程序中声明它,广播它,然后在每个执行器中得到它的值。运行应用程序时,会引发以下异常: Exception in thread "main" java.io.NotSerializableException: database.Database 注: executors类是可序列化的 广播对象在该类中定义为瞬态 我删除了瞬态,但它不工作 我这样理解你的问题:

我有一个数据库对象,用于插入来自所有Spark执行器的数据。当我将这个对象定义为
static
时,这些执行器中有一个
null
值。所以我在驱动程序中声明它,广播它,然后在每个执行器中得到它的值。运行应用程序时,会引发以下异常:

Exception in thread "main" java.io.NotSerializableException: database.Database
注:

  • executors类是可序列化的
  • 广播对象在该类中定义为瞬态
  • 我删除了瞬态,但它不工作

    • 我这样理解你的问题:

      我想从我的RDD中插入来自所有Spark执行器的数据。我试图在驱动程序上创建一个DB连接,并以某种方式将其作为广播传递给执行器,但Spark不断抛出
      NotSerializableException
      。我怎样才能实现我的目标

      简单的回答是:

      您应该在每个executor节点上分别创建一个新连接。
      您不应该将数据库连接处理程序、文件处理程序等传递给其他进程,尤其是远程机器

      这里的问题是在何处创建数据库连接,因为有大量的执行器,很容易超过数据库的连接池大小

      实际上,您可以使用以下方法:

        // numPartitions == number of simultaneous DB connections you can afford
        yourRdd.repartition(numPartitions)
        .foreachPartition {
          iter =>
            val connection = createConnection()
            while (iter.hasNext) {
              connection.execute("INSERT ...")
            }
            connection.commit()
        }
      
      这里,
      .foreachPartition
      中的代码将在每个执行器机器上执行,连接对象不会通过网络发送,不会出现序列化异常,数据将被插入


      关于使用
      foreachPartition
      的相同推理也在问题的答案中提到。

      我这样解释您的问题:

      我想从我的RDD中插入来自所有Spark执行器的数据。我试图在驱动程序上创建一个DB连接,并以某种方式将其作为广播传递给执行器,但Spark不断抛出
      NotSerializableException
      。我怎样才能实现我的目标

      简单的回答是:

      您应该在每个executor节点上分别创建一个新连接。
      您不应该将数据库连接处理程序、文件处理程序等传递给其他进程,尤其是远程机器

      这里的问题是在何处创建数据库连接,因为有大量的执行器,很容易超过数据库的连接池大小

      实际上,您可以使用以下方法:

        // numPartitions == number of simultaneous DB connections you can afford
        yourRdd.repartition(numPartitions)
        .foreachPartition {
          iter =>
            val connection = createConnection()
            while (iter.hasNext) {
              connection.execute("INSERT ...")
            }
            connection.commit()
        }
      
      这里,
      .foreachPartition
      中的代码将在每个执行器机器上执行,连接对象不会通过网络发送,不会出现序列化异常,数据将被插入


      关于使用
      foreachPartition
      的相同推理也在问题的答案中提到。

      数据库对象的意思是什么?DTO或其他什么?请看一看并相应地重写您的问题。我创建了一个类来处理连接到数据库和所有数据库交互。您不能序列化数据库连接。它正确地叫喊着
      java.io.NotSerializableException
      很好。这就是为什么我使用广播,在所有执行者之间共享这个对象。假设我得到了这个异常,这是否意味着广播变量应该是可序列化的?数据库对象的意思是?DTO或其他什么?请看一看并相应地重写您的问题。我创建了一个类来处理连接到数据库和所有数据库交互。您不能序列化数据库连接。它正确地叫喊着
      java.io.NotSerializableException
      很好。这就是为什么我使用广播,在所有执行者之间共享这个对象。假设我得到了这个异常,这是否意味着广播变量应该是可序列化的?