Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/apache-spark/5.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
Apache spark 避免不平衡火花_Apache Spark_Rdd_Shuffle_Hadoop Partitioning - Fatal编程技术网

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
transformation
aggregateByKey.
问题在于,几乎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
    )
    

“问题在于,几乎98%的RDD元素具有相同的密钥”这么多元素具有相同的密钥是有原因的吗?这是业务需求吗?实际上我不知道,我没有任何功能知识,我只是想找到性能瓶颈。我必须考虑他们已经考虑过并且分区是正确的。也许如果密钥生成更好,并且理想地统一,那么在单个分区太大的情况下,你就不会有问题了。但是你可以看到,它们也是一个聚合密钥,所以我应该在不改变代码的情况下尝试解决,而不是转换转换。毫无疑问,这是一段非常糟糕的代码。我只想知道,在不改变程序逻辑的情况下,是否有任何快速而肮脏的解决方案,我在想分区是否可以解决或至少缓解性能问题