Spark Streaming:在UpdateStateByKey之后连接回原始流

时间:2016-03-09 13:02:02

标签: scala apache-spark spark-streaming

我正在Spark Streaming中编写一个应用程序,我需要计算double值的指数移动平均值并将该平均值添加到行中。 这个平均值计算如下:

  

EMA(t)= EMA(t-1)* 0.75 + Value(t)* 0.25

每个时间间隔我都有一行数据来源:

  

(name1-24 / 04/2015 15:31;观察(名称1; 24/04/2015 15:31; 132.45))

     

(name2-24 / 04/2015 15:31;观察(名称2; 24/04/2015 15:31; 20.5))

我的唯一键是粘贴在一起的名称和时间戳。然后我将名称和时间戳分开,然后我的双倍值。我将跟踪每个不同名称的指数移动平均值。

我正在使用updateStateByKey()完成此操作: (名称将是此操作中的关键,因为我需要每个名称的平均值)

case class Observation(name: String, time: Timestamp, outcome: Double)

val outcomeDstream: DStream[(String, Double)] = 
    parsedstream.map { case (k: String, obs: Observation) => (obs.name, obs.close) }

def updateEMA(newValues: Seq[Double],oldCount: Option[Double]): Option[Double] = {
  if (oldCount.isEmpty) newValues(0)
  else Some((newValues(0)*0.25) + (oldCount.get*(0.75)))
}

val ema = outcomeDstream.updateStateByKey[Double](updateEMA _)

我遇到的问题是:如果我使用此函数来跟踪我的指数移动平均线,它将返回我:(name,expMovAvg)。但是我将丢失我的唯一密钥和时间戳。这个问题是我无法将这个ema-Dstream加入到我的原始流中,因为我的密钥现在只是不唯一的名称。

在updateStateByKey转换过程中是否有可能保留唯一键或时间戳?

1 个答案:

答案 0 :(得分:1)

如果我正确理解您的问题,您可以使用Option[Double]作为名称作为键的状态,而不是将updateStateByKey保持为Option[Observation]状态,其中包含您需要的所有独特数据:

val outcomeDstream: DStream[(String, Observation)] = 
    parsedstream.map { case (k: String, obs: Observation) => (obs.name, obs) }

def updateEMA(newValues: Seq[Observation], 
              oldCount: Option[Observation]): Option[Observation] = {
  if (oldCount.isEmpty) newValues(0)
  else Some((newValues(0).outcome * 0.25) + (oldCount.get.outcome * (0.75)))
}

作为旁注,如果您使用的是Spark 1.6.0,请考虑查看PairDStreamFunctions.mapWithState。虽然语义稍有不同(它不会处理没有收到新值的键)但仍然是实验性的,it is superior in performance