【问题标题】:spark streaming update_state_by_keys for arrays aggregation用于数组聚合的火花流 update_state_by_keys
【发布时间】:2016-06-04 11:36:15
【问题描述】:

我有如下输入行

t1, 文件1, 1, 1, 1

t1, 文件1, 1, 2, 3

t1, 文件2, 2, 2, 2, 2

t2, 文件1, 5, 5, 5

t2, 文件2, 1, 1, 2, 2

下面几行的输出是对应数字的垂直相加。

file1 : [ 1+, 1+2+5, 1+3+5 ]

文件2:[2+1、2+1、2+2、2+2]

目前数据聚合逻辑适用于批处理间隔,但它不维护状态。所以,我正在添加 update_state_by_key 函数并传递下面的函数,这是正确的方法吗?

我目前的计划:

    def updateValues( newValues: Seq[Array[Int]], currentValue: Option[Array[Int]]) = {

        val previousCount = currentValue.getOrElse(Array.fill[Byte](newValues.length)(0))
        val allValues = newValues +: previousCount
        Some(allValues.toList.transpose.map(_.sum).toArray)

      }

def main(args: Array[String]): Unit = {
    val conf = new SparkConf().setAppName("HBaseStream")
    val sc = new SparkContext(conf)
    // create a StreamingContext, the main entry point for all streaming functionality
    val ssc = new StreamingContext(sc, Seconds(2))
    // parse the lines of data into coverage objects
    val inputStream = ssc.socketTextStream(<hostname>, 9999)
    ssc.checkpoint("<hostname>:8020/user/spark/checkpoints_dir")
    inputStream.print(10)
    val parsedDstream = inputStream
      .map(line => {
        val splitLines = line.split(",")
        (splitLines(1), splitLines.slice(2, splitLines.length).map(_.trim.toInt))
      })
    val aggregated_file_counts = parsedDstream.updateStateByKey(updateValues)

        // Start the computation
    ssc.start()
    // Wait for the computation to terminate
    ssc.awaitTermination()

  }

作为参考,我之前的程序(没有状态转换):

def main(args: Array[String]): Unit = {
        val conf = new SparkConf().setAppName("HBaseStream")
        val sc = new SparkContext(conf)
        // create a StreamingContext, the main entry point for all streaming functionality
        val ssc = new StreamingContext(sc, Seconds(2))
        val inputStream = ssc.socketTextStream("hostname", 9999)
        val parsedDstream = inputStream
          .map(line => {
            val splitLines = line.split(",")
            (splitLines(1), splitLines.slice(2, splitLines.length).map(_.trim.toInt))
          })
          .reduceByKey((first, second) => {
            val listOfArrays = ArrayBuffer(first, second)
            listOfArrays.toList.transpose.map(_.sum).toArray
          })
          .foreachRDD(rdd => rdd.foreach(Blaher.blah))
    }

提前致谢。

【问题讨论】:

    标签: scala apache-spark spark-streaming


    【解决方案1】:

    您要查找的是updateStateByKey。对于DStream[(T, U)],它应该采用一个带有两个参数的函数:

    • Seq[U] - 表示当前窗口的状态
    • Option[U] - 表示累积状态

    并返回Option[U]

    鉴于您的代码,它可以像这样实现:

    import breeze.linalg.{DenseVector => BDV}
    import scala.util.Try
    
    val state: DStream[(String, Array[Int])] = parsedStream.updateStateByKey(
      (current: Seq[Array[Int]], prev: Option[Array[Int]]) =>  {
        prev.map(_ +: current).orElse(Some(current))
        .flatMap(as => Try(as.map(BDV(_)).reduce(_ + _).toArray).toOption)
    })
    

    您必须configure checkpointing才能使用它。

    【讨论】:

    • 感谢 Zero323,我刚刚编辑了我的问题并看到了您的回答。我正在检查您的方法,将更新。再次感谢。
    • 嗨 zero323,它工作正常,但是当我终止程序并再次盯着我的程序时,它从头开始计算。这是预期的行为吗?我可以更改有状态转换中的任何设置,以便它记住以前的状态吗?
    猜你喜欢
    • 1970-01-01
    • 2019-02-27
    • 2020-08-06
    • 1970-01-01
    • 1970-01-01
    • 2018-11-08
    • 1970-01-01
    • 2021-11-19
    • 1970-01-01
    相关资源
    最近更新 更多