Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sqlite/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala 用于超过内存限制的杀纱容器_Scala_Apache Spark_Apache Spark Sql_Emr_Amazon Emr - Fatal编程技术网

Scala 用于超过内存限制的杀纱容器

Scala 用于超过内存限制的杀纱容器,scala,apache-spark,apache-spark-sql,emr,amazon-emr,Scala,Apache Spark,Apache Spark Sql,Emr,Amazon Emr,我遇到了一个问题,纱线因为超过内存限制而杀死了我的容器: Container killed by YARN for exceeding memory limits. physical memory used. Consider boosting spark.yarn.executor.memoryOverhead. 我有20个m3.2x大的节点,因此它们有: cores: 8 memory: 30 storage: 200 gb ebs 我的应用程序的要点是,我有一对10万资产,我有去年每小

我遇到了一个问题,纱线因为超过内存限制而杀死了我的容器:

Container killed by YARN for exceeding memory limits. physical memory used. Consider boosting spark.yarn.executor.memoryOverhead.
我有20个m3.2x大的节点,因此它们有:

cores: 8
memory: 30
storage: 200 gb ebs
我的应用程序的要点是,我有一对10万资产,我有去年每小时生成的历史数据,总数据集大小为2TB未压缩。我需要使用这些历史数据为每项资产生成预测。我的设置是首先使用s3distcp将作为索引lzo文件存储的数据移动到hdfs。然后,我将数据拉入并将其传递给sparkSql以处理json:

 val files = sc.newAPIHadoopFile("hdfs:///local/*",
  classOf[com.hadoop.mapreduce.LzoTextInputFormat],classOf[org.apache.hadoop.io.LongWritable],
  classOf[org.apache.hadoop.io.Text],conf)
val lzoRDD = files.map(_._2.toString)
val data = sqlContext.read.json(lzoRDD)
然后,我使用groupBy按资产对历史数据进行分组,创建一个元组(assetId、timestamp、sparkSqlRow)。我认为,在生成每项资产的预测时,这种数据结构将允许更好的内存操作

 val p = data.map(asset =>  (asset.getAs[String]("assetId"),asset.getAs[Long]("timestamp"),asset)).groupBy(_._1)
然后我使用foreach迭代每一行,计算预测,最后将预测作为json文件写回s3

 p.foreach{ asset =>
  (1 to dateTimeRange.toStandardHours.getHours).foreach { hour =>
    // determine the hour from the previous year
    val hourFromPreviousYear = (currentHour + hour.hour) - timeRange
    // convert to seconds
    val timeToCompare = hourFromPreviousYear.getMillis
    val al = asset._2.toList

    println(s"Working on asset ${asset._1} for hour $hour with time-to-compare: $timeToCompare")
    // calculate the year over year average for the asset
    val yoy = calculateYOYforAsset2(al, currentHour, asset._1)
    // get the historical data for the asset from the previous year
    val pa = asset._2.filter(_._2 == timeToCompare)
      .map(row => calculateForecast(yoy, row._3, asset._1, (currentHour + hour.hour).getMillis))
      .foreach(json => writeToS3(json, asset._1, (currentHour + hour.hour).getMillis))
  }
}
  • 有没有更好的方法来实现这一点,这样我就不会碰到纱线的内存问题
  • 有没有一种方法可以将这些资产分块,使foreach一次只能处理大约10k的资产,而不是全部200k的资产

感谢您的任何建议/帮助

这不是你的代码。别担心,
foreach
不会同时运行所有这些lambda。问题是Spark的默认值
Spark.Thread.executor.memoryOverhead
(或最近在2.3+中重命名为
Spark.executor.memoryOverhead
)过于保守,这会导致执行器在负载下被杀死

解决方案是(按照错误消息的建议)增加该值。如果您要为每个执行器请求大量内存,我会首先将其设置为1GB(设置为
1024
)或更多。目标是让作业运行,而不会杀死任何执行者


或者,如果您控制集群,您可以通过在
warn site.xml

中将configs
warn.nodemanager.pmem check enabled
warn.nodemanager.vmem check enabled
设置为
false
来禁用纱线内存强制执行。您可能会遇到与我在本答案中给出的示例类似的问题: