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
}
}
}
}
}