Apache spark 避免不平衡火花
我对正在修改的代码有性能问题,每次执行计数时都会给出Apache spark 避免不平衡火花,apache-spark,rdd,shuffle,hadoop-partitioning,Apache Spark,Rdd,Shuffle,Hadoop Partitioning,我对正在修改的代码有性能问题,每次执行计数时都会给出OOM。 我想我发现了问题,基本上是在执行keyBytransformationaggregateByKey. 问题在于,几乎98%的RDD元素具有相同的密钥,因此aggregationByKey、generate shuffle、将几乎所有记录放入同一个分区中,底线是:只有很少的执行器可以工作,并且需要很大的内存压力 代码如下: val rddAnomaliesByProcess : RDD[AnomalyPO] = rddAnomalies
OOM
。
我想我发现了问题,基本上是在执行keyBy
transformationaggregateByKey.
问题在于,几乎98%的RDD元素具有相同的密钥,因此aggregationByKey、generate shuffle、将几乎所有记录放入同一个分区中,底线是:只有很少的执行器可以工作,并且需要很大的内存压力
代码如下:
val rddAnomaliesByProcess : RDD[AnomalyPO] = rddAnomalies
.keyBy(po => po.getProcessCreator.name)
.aggregateByKey(List[AnomalyPO]())((list,value) => value +: list,_++_)
.map {case(name,list) =>
val groupByKeys = list.groupBy(po => (po.getPodId, po.getAnomalyCode, po.getAnomalyReason, po.getAnomalyDate, po.getMeasureUUID))
val lastOfGroupByKeys = groupByKeys.map{po => (po._1, List(po._2.sortBy { po => po.getProcessDate.getMillis }.last))}
lastOfGroupByKeys.flatMap(f => f._2)
}
.flatMap(f => f)
log.info("not duplicated Anomalies: " + rddAnomaliesByProcess.count)
我希望找到一种更并行的方式来执行操作,允许所有执行者几乎平等地工作。我该怎么做
我应该使用自定义分区器吗?如果您的观察正确且 98%的RDD元素具有相同的密钥 那么换一个选区对你一点帮助都没有。根据分区器的定义,98%的数据必须由单个执行器处理 幸运的是,坏代码可能比歪斜更大。跳过:
.aggregateByKey(List[AnomalyPO]())((List,value)=>value+:List,++)
这只是一个民间魔术,看起来整个管道可以重写为一个简单的reuceByKey
。伪代码:
- 将
和本地键组合成一个键:name
包含名称、日期和其他字段的键的基数应该比单独的名称高得多def键(po:AnomalyPO)=( //“主要”键 po.getProcessCreator.name, //“小调”键 po.getPodId,po.getAnomalyCode, po.getAnomalyReason,po.getAnomalyDate,po.getmeasureuid )
- 映射到配对并按键减少:
rddAnomalies .map(po=>(键(po),po)) .reduceByKey((x,y)=> 如果(x.getProcessDate.getMillis>y.getProcessDate.getMillis)x其他y )