Scala spark 2.0并行JobProgressListener严重失败

Scala spark 2.0并行JobProgressListener严重失败,scala,apache-spark,parallel-processing,apache-spark-sql,scala-collections,Scala,Apache Spark,Parallel Processing,Apache Spark Sql,Scala Collections,我有一个场景,需要使用for循环并行触发许多sql查询,并将结果列表收集到ListBuffer中。 但是,我在运行循环时遇到许多错误,结果并不完整。为了举例说明,我制作了一个非常简单的可复制示例: import scala.collection.mutable.ListBuffer val dummy = List("a","b").toDF.createOrReplaceTempView("df") spark.catalog.cacheTable("df") val dig = (0 to

我有一个场景,需要使用
for
循环并行触发许多sql查询,并将结果列表收集到
ListBuffer
中。 但是,我在运行循环时遇到许多错误,结果并不完整。为了举例说明,我制作了一个非常简单的可复制示例:

import scala.collection.mutable.ListBuffer
val dummy = List("a","b").toDF.createOrReplaceTempView("df")
spark.catalog.cacheTable("df")
val dig = (0 to 9).par
var counter = 0:Int
var results = ListBuffer[List[org.apache.spark.sql.Row]]()

for (i1 <- dig ) {
   for (i2 <- dig ) {
     for (i3 <- dig ) {
        println("||==="+i1+"=="+i2+"=="+i3+"===="+(i1*100+i2*10+i3*1)+"===="+counter+"=======||")
        counter +=1
        results += spark.sql("select 'trial','"+i1+"','"+i2+"','"+i3+"','"+(i1*100+i2*10+i3*1)+"','"+counter+"',*  from df ").collect().toList
       }
     }
   }
results(0).take(2).foreach(println)
results.size
results.flatten.size
这些只是我得到的一些警告

您可以看到计数器有时会“交错”

**麻烦就从这里开始**

大量警告,但
results.size=1000
results.flatte.size=2000
与预期一致

但是,尝试以相同方式计数到10000会导致更多警告:

import scala.collection.mutable.ListBuffer
val dummy = List("a","b").toDF.createOrReplaceTempView("df")
spark.catalog.cacheTable("df")
val dig = (0 to 9).par
var counter = 0:Int
var results = ListBuffer[List[org.apache.spark.sql.Row]]()

for (i1 <- dig ) {
   for (i2 <- dig ) {
     for (i3 <- dig ) {
       for (i4 <- dig ) {
         println("||==="+i1+"=="+i2+"=="+i3+"=="+i4+"===="+(i1*1000+i2*100+i3*10+i4*1)+"===="+counter+"=======||")
         counter +=1
         results += spark.sql("select 'trial','"+i1+"','"+i2+"','"+i3+"', '"+i4+"','"+(i1*1000+i2*100+i3*10+i4*1)+"','"+counter+"',*  from df ").collect().toList
       }
     }
   }
 }
results(0).take(2).foreach(println)
results.size
results.flatten.size
结果是:

scala> results(0).take(2).foreach(println)
[trial,3,0,0,0,3000,7,a]
[trial,3,0,0,0,3000,7,b]

scala> results.size
res3: Int = 9999

scala> results.flatten.size
res4: Int = 19998
缺少一个值

我邀请您尝试以下计数为100000的代码:

import scala.collection.mutable.ListBuffer
val dummy = List("a","b").toDF.createOrReplaceTempView("df")
spark.catalog.cacheTable("df")
val dig = (0 to 9).par
var counter = 0:Int
var results = ListBuffer[List[org.apache.spark.sql.Row]]()

for (i0 <- dig ) {
  for (i1 <- dig ) {
    for (i2 <- dig ) {
      for (i3 <- dig ) {
        for (i4 <- dig ) {
          println("============="+i0+"=="+i1+"=="+i2+"=="+i3+"=="+i4+"===="+(i0*10000+i1*1000+i2*100+i3*10+i4*1)+"===="+counter+"=========") 
          counter +=1
          results += spark.sql("select 'trial','"+i0+"','"+i1+"','"+i2+"','"+i3+"', '"+i4+"','"+(i0*10000+i1*1000+i2*100+i3*10+i4*1)+"','"+counter+"',*  from df ").collect().toList
        }
      }
    }
  }
}
在我的实际例子中,我经常在运行的随机点出现“spark.sql.execution.id已设置”异常

我怎样才能解决这个问题

我试过了

spark.conf.set("spark.extraListeners","org.apache.spark.scheduler.StatsReportListener,org.apache.spark.scheduler.EventLoggingListener")
阅读

和副作用的操作,但似乎有太多的方向

与此问题最相关的bug是imho 这应该在spark 1.6中解决

有人能提供一些关于解决这种情况的提示吗?我现实世界案例的复杂性类似于100000计数,在随机阶段执行时失败

我部署了一个GCS dataproc集群

gcloud dataproc集群创建集群st--zone us-central1-b--master machine type n1-highmem-16--num workers 2--worker machine type n1-highmem-8--num worker local ssd 2--num preemptive worker 8--scopes'https://www.googleapis.com/auth/cloud-platform“--项目xyz分析

结果是不完整和不确定的

非确定性部分应该给出一个提示。将结果添加到
ListBuffer
(并行更新并不是真正的线程安全,因此如果运行时间足够长,最终会丢失一些结果)时,您将陷入竞争状态

我在本地进行了尝试,可以重现这个不完整的结果问题。只需添加一个用于附加到缓冲区的同步块,即可完成结果。您还可以为您的作业使用其他
synchronized
数据结构,因此无需放置显式
synchronized
块,例如
java.util.concurrent.ConcurrentLinkedQueue
或其他什么

因此,下面解决了这个问题:

for (i1 <- dig ) {
   for (i2 <- dig ) {
     for (i3 <- dig ) {
       for (i4 <- dig ) {
         counter +=1
         val result = spark.sql("select 'trial','"+i1+"','"+i2+"','"+i3+"', '"+i4+"','"+(i1*1000+i2*100+i3*10+i4*1)+"','"+counter+"',*  from df ").collect().toList
         synchronized {
           results += result
         }
       }
     }
   }
 }

for(i1)您使用的是Spark的哪个版本?google gcsjava.lang.IllegalArgumentException:Spark.sql.execution.id已在org.apache.Spark.sql.execution.SQLExecution$.withNewExecutionId(SQLExecution.scala:81)中设置在org.apache.Spark.sql.Dataset.withNewExecutionId(Dataset.scala:2532)中org.apache.spark.sql.Dataset.org$apache$spark$sql$Dataset$$execute$1(Dataset.scala:2182)org.apache.spark.sql.Dataset$$anonfun$org$apache$spark$sql$Dataset$$collect$1.apply(Dataset.scala:2187)at…在我看来像是个bug。显然,其他一些人也报告说在2.0()即使它被标记为已解决。也必须深入研究代码以了解根本原因。是的,我看到了这个错误,并希望它与此相关。
scala> results(0).take(2).foreach(println)
[trial,8,5,0,0,0,85000,13,a]
[trial,8,5,0,0,0,85000,13,b]

scala> results.size
res3: Int = 99999

scala> results.flatten.size
res4: Int = 192908
spark.conf.set("spark.extraListeners","org.apache.spark.scheduler.StatsReportListener,org.apache.spark.scheduler.EventLoggingListener")
for (i1 <- dig ) {
   for (i2 <- dig ) {
     for (i3 <- dig ) {
       for (i4 <- dig ) {
         counter +=1
         val result = spark.sql("select 'trial','"+i1+"','"+i2+"','"+i3+"', '"+i4+"','"+(i1*1000+i2*100+i3*10+i4*1)+"','"+counter+"',*  from df ").collect().toList
         synchronized {
           results += result
         }
       }
     }
   }
 }