【问题标题】:Not able to repartition the DStream无法重新分区 DStream
【发布时间】:2017-07-02 13:10:53
【问题描述】:
val sparkConf = new SparkConf().setMaster("yarn-cluster")
                               .setAppName("SparkJob")
                               .set("spark.executor.memory","2G")
                               .set("spark.dynamicAllocation.executorIdleTimeout","5")

val streamingContext = new StreamingContext(sparkConf, Minutes(1))

var historyRdd: RDD[(String, ArrayList[String])] = streamingContext.sparkContext.emptyRDD

var historyRdd_2: RDD[(String, ArrayList[String])] = streamingContext.sparkContext.emptyRDD

val stream_1 = KafkaUtils.createDirectStream[String, GenericData.Record, StringDecoder, GenericDataRecordDecoder](streamingContext, kafkaParams ,  Set(inputTopic_1))
val dstream_2 = KafkaUtils.createDirectStream[String, GenericData.Record, StringDecoder, GenericDataRecordDecoder](streamingContext, kafkaParams ,  Set(inputTopic_2))

val dstream_2 = stream_2.map((r: Tuple2[String, GenericData.Record]) => 
{
    //some mapping
}

dstream_1.foreachRDD(r => r.repartition(500))
val historyDStream = dstream_1.transform(rdd => rdd.union(historyRdd))
dstream_2.foreachRDD(r => r.repartition(500))
val historyDStream_2 = dstream_2.transform(rdd => rdd.union(historyRdd_2))
val fullJoinResult = historyDStream.fullOuterJoin(historyDStream_2)

val filtered = fullJoinResult.filter(r => r._2._1.isEmpty)


filtered.foreachRDD{rdd =>
    val formatted = rdd.map(r  => (r._1 , r._2._2.get)) 
    historyRdd_2.unpersist(false) // unpersist the 'old' history RDD
    historyRdd_2 = formatted // assign the new history
    historyRdd_2.persist(StorageLevel.MEMORY_AND_DISK) // cache the computation
}

val filteredStream = fullJoinResult.filter(r => r._2._2.isEmpty)

filteredStream.foreachRDD{rdd =>
    val formatted = rdd.map(r => (r._1 , r._2._1.get)) 
    historyRdd.unpersist(false) // unpersist the 'old' history RDD
    historyRdd = formatted // assign the new history
    historyRdd.persist(StorageLevel.MEMORY_AND_DISK) // cache the computation
}

streamingContext.start()
streamingContext.awaitTermination()
}
}

我无法使用上面的代码对 DStream 进行重新分区,我的输入得到了 128 个分区,这是没有的。 Kafka 分区,并且由于 Join 我需要随机读取和写入数据,所以我想通过增加分区数来增加并行度。但是分区保持不变。为什么会这样?

【问题讨论】:

    标签: spark-streaming apache-spark-2.0


    【解决方案1】:

    就像mapfilter 一样,repartition 是 Spark 中的转换,意味着 3 件事:

    • 它返回另一个不可变的 RDD
    • 很懒
    • 它需要通过一些动作来实现

    考虑这段代码:

    dstream_1.foreachRDD(r => r.repartition(500))
    

    foreachRDD 中使用repartition 作为副作用没有任何作用。生成的 RDD 永远不会被使用,因此重新分区永远不会发生。

    我们应该将这种转换与作业中的其他操作“链接”起来。在这种情况下,实现此目的的一种简单方法是改用transform

    val repartitionedDStream = dstream_1.transform(rdd => rdd.repartition(500))
    ... use repartitionedDStream further on ...
    

    【讨论】:

    • 如何最小化随机播放?加入前有 131 个分区用于联合 dstream(128 个 dstream + 3 个历史),加入后有 3 个分区,我可以做些什么来调整我的应用程序。重新分区也会增加处理时间,而不会影响改组
    • @massg 为什么在执行联合任务的阶段会有洗牌。
    • @JSR29 随机播放由join 触发。工会只是导致这种洗牌的阶段。这个解释挺好的:thread.gmane.org/gmane.comp.lang.scala.spark.user/4887
    • 在 union 的两个阶段都有随机读取来生成 historyDstream_1 和 historyDStream_2。我从 web UI 的阶段推断出这一点,因为我的工作分为三个阶段 a)Union(historyDStream_1) , b)Union (historyDStream_2) c)加入
    • 如果分区器不相等,您似乎可以进行联合触发的洗牌。在这种情况下值得检查。
    猜你喜欢
    • 1970-01-01
    • 2019-01-28
    • 2016-02-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-14
    • 2013-10-15
    • 1970-01-01
    相关资源
    最近更新 更多