Spark rdd使用collect方法生成OutOfMemoryError

时间:2019-05-16 12:17:43

标签: java scala apache-spark

我需要遍历rdd,取出要处理的数据并将其放入listbuffer。当我使用collect方法时,错误如下java.lang.OutOfMemoryError:超出了GC开销限制。否则,列表缓冲区为空。

这是我的代码:

val recoList = new ListBuffer[(String,String)]()
preUserProdcut.map(row =>(row._1,row._2))
  .foreach(row => {
    val recoItemList = new ListBuffer[String]()
    val userId = row._1
    val size = row._2.size
    for (i <- 0 to(size -1)){
      recoItemList.append(int2ItemIdMap.getOrElse(row._2(i).product,""))
    }
    recoList.append((RecoModelEnum.UserCF_fqd_01.modelId + "_" +userId.toString,recoItemList.mkString(",")))
    println("############" + recoList.size)  //1. here length is ok
  })

println("############" + recoList.size)     //2. this code doesn't be executed

当我使用collect方法时,代码可以在小型数据集上正常工作

preUserProdcut.map(row =>(row._1,row._2))
  .collect()
  .foreach(row => {.........})
println("############" + recoList.size)     //here length is ok

但是,当数据量很大时,错误代码要在spark集群上运行,错误如下:Java。郎OutOfMemoryError:超出了GC开销限制。

我尝试了以下几种方法:

sparkConf.set("dfs.client.block.write.replace-datanode-on-failure.policy","NEVER")
sparkConf.set("dfs.client.block.write.replace-datanode-on-failure.enable","true")
sparkConf.set("spark.rdd.compress", "true")

缓存数据和设置分区不起作用

preForUsersRdd.map(row =>(row._1,row._2)).persist().repartition(100).collect().foreach(row => {....})

设置驱动程序内存和执行者内存也无效

我知道collect方法会将数据添加到内存中,由于数据量大,容易出现错误

如何优化代码,如何使用collect方法。如果没有collect方法,则列表缓冲区为空。使用collect方法时内存不足

PreUserProduct作为sparkMllib的结果。 ALS。 RecommendProductsForUsers返回,结果形式为

[(Int, Array[Rating])] objects, where every tuple contains a userID and an array of rating objects which contains the same userId, recommended productID and     a "score" in the rating field.

因此,我需要使用foreach,listbuffer,collect等来迭代,处理和获取所需的格式(useid,product1,product2,.....)。然后通过sc。 MakeRDD(列表缓冲区),获取RDD,编写redis以供使用

collect方法是将数据收集到驱动程序中,这很容易出错

1 个答案:

答案 0 :(得分:-1)

我不明白您为什么需要使用ListBuffer

您应该使用write而不是collect