Apache Spark Map工作缓慢

时间:2017-12-18 18:01:28

标签: java apache-spark elasticsearch

我一直在尝试使用Apache Spark来查看它是否可用于为我们存储在Elasticsearch集群中的数据创建分析引擎。我发现,对于任何重要的RDD大小(即数百万条记录),即使最简单的操作也需要超过一分钟。

例如,我制作了这个简单的测试程序:

package es_spark;

import java.util.Map;

import org.apache.spark.SparkConf;
import org.apache.spark.api.java.JavaPairRDD;
import org.apache.spark.api.java.JavaRDD;
import org.apache.spark.api.java.JavaSparkContext;
import org.elasticsearch.spark.rdd.api.java.JavaEsSpark;

public class Main {

    public static void main (String[] pArgs) {

        SparkConf conf = new SparkConf().setAppName("Simple Application");
        conf.set("es.nodes", pArgs[0]);

        JavaSparkContext sc = new JavaSparkContext(conf);

        long start = System.currentTimeMillis();
        JavaPairRDD<String, Map<String, Object>> esRDD = JavaEsSpark.esRDD(sc, "test3");
        long numES = esRDD.count();
        long loadStop = System.currentTimeMillis();

        JavaRDD<Integer> dummyRDD = esRDD.map(pair -> {return 1;});
        long numDummy = dummyRDD.count();
        long mapStop = System.currentTimeMillis();

        System.out.println("ES Count: " + numES);
        System.out.println("ES Partitions: " + esRDD.getNumPartitions());

        System.out.println("Dummy Count: " + numDummy);
        System.out.println("Dummy Partitions: " + dummyRDD.getNumPartitions());

        System.out.println("Data Load Took: " + (loadStop - start) + "ms");
        System.out.println("Dummy Map Took: " + (mapStop - loadStop) + "ms");

        sc.stop();
        sc.close();
    }
}

我在一个带有3个从站的火花簇上运行它,每个从站有14个核心和49.0GB的RAM。使用以下命令:

./bin/spark-submit --class es_spark.Main --master spark://<master_ip>:7077 ~/es_spark-0.0.1.jar <elasticsearch_main_ip>

输出结果为:

ES Count: 8140270
ES Partitions: 80
Dummy Count: 8140270
Dummy Partitions: 80
Data Load Took: 108059ms
Dummy Map Took: 104128ms

在800多万条记录上执行虚拟地图作业需要1.5分钟以上。鉴于地图工作什么也没做,我觉得这个表现出奇的低。我做错了什么,或者这是关于Spark的正常表现吗?

我也尝试过对--executor-memory--executor-cores进行调整,没有多大区别。

2 个答案:

答案 0 :(得分:0)

一般情况下,除非您看到OOM故障或重要GC或溢出到磁盘作为瓶颈,否则不值得更改执行程序内存。当你改变它时,你也应该减少spark.memory.fraction。对于你的工作,它几乎不可能提供帮助。

Spark的启动成本使得对于较小的数据加载而言效率相对较低。您应该能够将启动时间优化到不到一分钟,但对于超大批量加载而言,它仍然更加实用,而不是实时分析。

我建议您使用DataFrame API而不是RDD。对于上面的简单示例操作,它无关紧要,但随着事情变得更加复杂,您更有可能从性能优化中受益。

e.g。 library(reshape2) mydfl <- melt(mydf) mydfl$ind <- with(mydfl, ave(C1, C1, variable, FUN = seq_along)) dcast(mydfl, C1 + ind ~ variable, sum, margins = c("C1", "ind", "variable")) # C1 ind X1 X2 (all) # 1 a 1 12 1 13 # 2 a 2 14 2 16 # 3 a (all) 26 3 29 # 4 b 1 16 3 19 # 5 b 2 11 4 15 # 6 b 3 8 5 13 # 7 b (all) 35 12 47 # 8 (all) (all) 61 15 76

要解决导致速度缓慢的问题,您可以查看Spark UI。你真的得到并行吗?所有工作在大致相同的时间内执行了吗?另一个可能的缓慢来源是群集和ES服务器之间的网络问题。

答案 1 :(得分:0)

  

鉴于地图工作什么都不做,发现这个性能出乎意料地低。

地图工作没有做任何事情。它必须从Elastic搜索中获取完整的数据集。因为数据没有缓存,所以它会发生两次,每次操作一次。这个时间还包括一些初始化时间。

总的来说,你衡量:

  • ES查询的时间。
  • Spark群集与ES之间的网络延迟。

和一些次要的事情,如:

  • 执行程序JVM完全初始化的时间。
  • Probablly GC暂停时间。
相关问题