我需要遍历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方法是将数据收集到驱动程序中,这很容易出错
答案 0 :(得分:-1)
我不明白您为什么需要使用ListBuffer
。
您应该使用write
而不是collect
。