是否可以通过火花流实时更新值?

时间:2015-05-15 09:40:39

标签: statistics apache-spark streaming

假设我有一个Double值流,我想每十秒计算一次平均值。我怎样才能有一个滑动窗口,不需要重新计算平均值,而是更新它,比如说,删除最旧的十秒部分,只添加新的10秒值?

1 个答案:

答案 0 :(得分:1)

TL;DR:使用reduceByWindow及其两个函数参数(跳转到代码段的最后一段)

您的问题有两种解释,具体的解释(如何获得一小时的运行平均值,每2秒更新一次)和一般的解释(如何获得更新状态的计算?稀疏的方式)。这是普通人的答案。

首先,请注意有一种方法可以表示您的数据,以便根据windowed DStream轻松计算您的平均更新数据:这表示您的数据是流的增量构造,具有最大值分享。但是,正如你所指出的那样,重新计算每批产品的平均值在计算上效率较低。

如果你确实想要更新一个可逆的复杂有状态计算,但又不想触及流的构造,那就有updateStateByKey - 但Spark并没有&# 39; t帮助您反映流中计算的增量方面,您必须自己管理它。

在这里,你确实有一些简单易懂的东西,而且你没有钥匙的概念。您可以使用reduceByWindow及其反向减少参数,使用通常的函数来计算增量平均值。

val myInitialDStream: DStream[Float]

val myDStreamWithCount: DStream[(Float, Long)] = 
  myInitialDStream.map((x) => (x, 1L))

def addOneBatchToMean(previousMean: (Float, Long), newBatch: (Float, Long)): (Float, Long) = 
  (previousMean._1 + newBatch._1, previousMean._2 + newBatch._2)

def removeOneBatchToMean(previousMean: (Float, Long), oldBatch: (Float, Long)): (Float, Long) = 
  (previousMean._1 - oldBatch._1, previousMean._2 - oldBatch._2)

val runningMeans = myDStreamWithCount.reduceByWindow(addOneBatchToMean, removeOneBatchToMean, Durations.seconds(3600), Duractions.seconds(2))

你得到一个单元素RDD的流,每个元素包含一对(m,n),其中m是你在1h窗口上的运行总和,n是1h中元素的数量 - 窗口。只需返回(或map至)m / n即可获得均值。