Streaming 如何使spark分区保持粘性,即留在节点上?

Streaming 如何使spark分区保持粘性,即留在节点上?,streaming,apache-spark,Streaming,Apache Spark,我正在尝试使用Spark Streaming 1.2.0。在某个时刻,我按键对流数据进行分组,然后对它们应用一些操作 以下是测试代码的一部分: ... JavaPairDStream<Integer, Iterable<Integer>> grouped = mapped.groupByKey(); JavaPairDStream<Integer, Integer> results = grouped.mapToPair(

我正在尝试使用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();
。。。
JavaPairDStream grouped=mapped.groupByKey();
JavaPairDStream结果=grouped.mapToPair(
新PairFunction(){
@凌驾
公共Tuple2调用(Tuple2 tp)引发异常{
TaskContext tc=TaskContext.get();
字符串ip=InetAddress.getLocalHost().getHostAddress();
int key=tp._1();
System.out.println(ip+”:分区:“+tc.partitionId()+”\tKey:“+key);
返回新的Tuple2(键,1);
}
});
结果:打印();
mapped是一个JavaPairDStream,它包装了一个虚拟接收器,该接收器每秒存储一个整数数组

我在一个有两个从机的集群上运行了这个应用程序,每个从机有2个内核。 当我签出打印输出时,似乎没有将分区永久地分配给节点(或以“粘性”方式)。它们经常在两个节点之间移动。这给我带来了一个问题

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

有没有办法使分区保持粘性,即分区0,1,2,3与节点0保持一致,分区4,5,6,7与节点1保持一致

我试过设置spark.locality.wait为一个很大的数字,比如1000000。但它没有起作用

谢谢。

我找到了解决办法。 我可以使我的辅助数据成为RDD。将其分区并缓存。 稍后,我可以将它与其他RDD组合,Spark将尝试保持缓存的RDD分区在原来的位置,而不是将它们洗牌。例如

...
JavaPairRDD<Integer, GeoData> geoRDD = 
    geoRDD1.partitionBy(new HashPartitioner(num)).cache();
。。。
javapairdd-geoRDD=
geoRDD1.partitionBy(新的HashPartitioner(num)).cache();
以后再做这个

JavaPairRDD<Integer, Integer> someOtherRDD = ...
JavaPairRDD<Integer, Tuple2<Iterator<GeoData>>, Iterator<Integer>>> grp =
    geoRDD.cogroup(someOtherRDD);
javapairdd someOtherRDD=。。。
javapairdd>grp=
geoRDD.cogroup(someotherdd);
然后,您可以在协同编组的rdd上使用foreach来处理带有地理数据的输入数据