如何使火花分区粘,即与节点保持一致?

时间:2015-01-21 23:50:11

标签: streaming apache-spark

我正在尝试使用Spark Streaming 1.2.0。在某些时候,我按键对流数据进行分组,然后对它们应用了一些操作。

以下是测试代码的一部分:

...        
JavaPairDStream<Integer, Iterable<Integer>> grouped = mapped.groupByKey();
JavaPairDStream<Integer, Integer> results = grouped.mapToPair(
            new PairFunction<Tuple2<Integer, Iterable<Integer>>, Integer, Integer>() {
                @Override
                public Tuple2<Integer, Integer> call(Tuple2<Integer, Iterable<Integer>> tp) throws Exception {
                    TaskContext tc = TaskContext.get();
                    String ip = InetAddress.getLocalHost().getHostAddress();
                    int key = tp._1();
                    System.out.println(ip + ": Partition: " + tc.partitionId() + "\tKey: " + key);
                    return new Tuple2<>(key, 1);
                }
            });
results.print();

mapped是一个JavaPairDStream,它包含一个虚拟接收器,每秒存储一个整数数组。

我在具有两个从属设备的群集上运行此应用程序,每个从属设备有2个核心。 当我签出打印输出时,似乎分区没有永久地(或以“粘性”方式)分配给节点。他们经常在两个节点之间移动。这给我带来了麻烦。

在我的实际应用程序中,我需要为每个分区加载相当大量的地理数据。这些地理数据将用于处理流中的数据。我只能负担每个分区加载部分地理数据集的费用。如果分区在节点之间移动,我将不得不移动地理数据,这可能非常昂贵。

有没有办法让分区变粘,即分区0,1,2,3留在节点0,分区4,5,6,7留在节点1?

我已经尝试将spark.locality.wait设置为一个很大的数字,比如说1000000。它没有用。

感谢。

1 个答案:

答案 0 :(得分:2)

我找到了解决方法。 我可以将辅助数据作为RDD。对它进行分区并缓存它。 稍后,我可以将其与其他RDD联合起来,Spark会尝试将缓存的RDD分区保留在原来的位置,而不是将它们随机播放。 E.g。

...
JavaPairRDD<Integer, GeoData> geoRDD = 
    geoRDD1.partitionBy(new HashPartitioner(num)).cache();

稍后,这样做

JavaPairRDD<Integer, Integer> someOtherRDD = ...
JavaPairRDD<Integer, Tuple2<Iterator<GeoData>>, Iterator<Integer>>> grp =
    geoRDD.cogroup(someOtherRDD);

然后,您可以在coroupped rdd上使用foreach来处理带有地理数据的输入数据。