【问题标题】:How history RDDs are preserved for further use in the given code如何保留历史 RDD 以供在给定代码中进一步使用
【发布时间】:2017-06-11 19:33:33
【问题描述】:
{
var history: RDD[(String, List[String]) = sc.emptyRDD()

val dstream1 = ...
val dstream2 = ...

val historyDStream = dstream1.transform(rdd => rdd.union(history))
val joined = historyDStream.join(dstream2)

... do stuff with joined as above, obtain dstreamFiltered ...

dstreamFiltered.foreachRDD{rdd =>
val formatted = rdd.map{case (k,(v1,v2)) => (k,v1) }
history.unpersist(false) // unpersist the 'old' history RDD
history = formatted // assign the new history
history.persist(StorageLevel.MEMORY_AND_DISK) // cache the computation
history.count() //action to materialize this transformation
}

此代码逻辑可以很好地保留所有先前未成功加入的 RDD 并为将来的批次保存,因此每当我们获得具有此 RDD 的相应加入键的记录时,我们执行加入但我没有不知道这段历史是如何建立起来的。

【问题讨论】:

    标签: spark-streaming


    【解决方案1】:

    在这种情况下,我们可以通过观察 RDD 谱系如何随时间演变来了解历史是如何建立的。

    我们需要两个先前的知识:

    • RDD 是不可变结构
    • RDD 上的操作可以通过要应用的函数和对输入 RDD 的引用以功能术语表示。

    让我们看一个简单的例子,使用经典的 wordCount:

    val txt = sparkContext.textFile(someFile)
    val words = txt.flatMap(_.split(" "))
    

    简而言之,txt 是 HadoopRDD(someFile)。 words 是 MapPartitionsRDD(txt, flatMapFunction)。我们将单词的lineage 称为由这种操作链接形成的 DAG(直接无环图)。:HadoopRDD <-- MapPartitionsRDD。

    我们可以将相同的原则应用于我们的流式操作:

    在第 0 次迭代中,我们有

    var history: RDD[(String, List[String]) = sc.emptyRDD()
    // -> history: EmptyRDD
    ...
    val historyDStream = dstream1.transform(rdd => rdd.union(history))
    // -> underlying RDD: rdd.union(EmptyRDD)
    join, filter
    // underlying RDD: ((rdd.union(EmptyRDD).join(otherRDD)).filter(pred)
    map
    // -> underlying RDD: ((rdd.union(EmptyRDD).join(otherRDD)).filter(pred).map(f) 
    history.unpersist(false)
    //  EmptyRDD.unpersist (does nothing, it was never persisted)
    history = formatted
    // history =  ((rdd.union(EmptyRDD).join(otherRDD)).filter(pred).map(f)
    history.persist(...)
    // history marked for persistence (at the next action)
    history.count()
    // ((rdd.union(EmptyRDD).join(otherRDD)).filter(pred).map(f).count()
    // cache result of:  ((rdd.union(EmptyRDD).join(otherRDD)).filter(pred).map(f)
    

    在第 1 次迭代中,我们有(添加 rdd0、rdd1 作为迭代索引):

    val historyDStream = dstream1.transform(rdd => rdd.union(history))
    // -> underlying RDD: rdd1.union(((rdd0.union(EmptyRDD).join(otherRDD0)).filter(pred).map(f))
    join, filter
    // underlying RDD: ((rdd1.union(((rdd0.union(EmptyRDD).join(otherRDD0)).filter(pred).map(f)).join(otherRDD1)).filter(pred)
    map
    // -> underlying RDD: ((rdd1.union(((rdd0.union(EmptyRDD).join(otherRDD0)).filter(pred).map(f)).join(otherRDD1)).filter(pred).map(f) 
    history.unpersist(false)
    //  history0.unpersist (marks the previous result for removal, we used it already for our computation above)
    history = formatted
    // history1 =  ((rdd1.union(((rdd0.union(EmptyRDD).join(otherRDD0)).filter(pred).map(f)).join(otherRDD1)).filter(pred).map(f)
    history.persist(...)
    // new history marked for persistence (at the next action)
    history.count()
    // ((rdd1.union(((rdd0.union(EmptyRDD).join(otherRDD0)).filter(pred).map(f)).join(otherRDD1)).filter(pred).map(f).count()
    // cache result sothat we don't need to compute it next time  
    

    这个迭代过程随着每次迭代而继续。

    正如我们所见,表示 RDD 计算的图表不断增长。 cache 降低了每次进行所有计算的成本。经常需要checkpoint 来编写这个增长图的具体计算值,以便我们可以将其用作基线,而不必评估整个链。

    查看此过程的一种有趣方式是在 foreachRDD 中添加一行来检查当前沿袭:

    ...
    history.unpersist(false) // unpersist the 'old' history RDD
    history = formatted // assign the new history
    println(history.toDebugString())
    ...
    

    【讨论】:

    • 你能帮我解决这个问题吗stackoverflow.com/questions/44492558/…
    • @JSR29 不习惯 :)
    • 顺便说一句,解释清楚了吗?您是否了解历史是如何随着时间的推移而积累起来的?
    • 我们使用检查点来获取 RDD,以防它们丢失,所以我们不需要重新计算,但是如果我们不检查点并且一些 RRD 丢失会发生什么情况,它会显示一些运行时异常还是什么?
    • A DStream 是 RDD 的连续序列,它不是单个 RDD,因此当您执行 history.unpersist 然后 history = formatted 时,它将替换相同过滤 DStream 的先前 RDD,就像在过滤后的 dstream 有 2 个 rdds R1 AND R2 ,所以在第一次迭代中,在块的开始你将取消保留空历史然后 history = formatted(R1) 然后在下一次迭代 history(R1).unpersist 和 history=formatted(R2) ,所以我们失去了 R1
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-29
    • 2013-10-19
    • 1970-01-01
    • 2012-03-25
    • 2012-11-22
    • 1970-01-01
    相关资源
    最近更新 更多