我想使用Apache Spark Streaming计算一周的窗口大小的滑动平均值。应及时提供结果,即具有亚分钟延迟。在我的情况下存储一周的流数据是不切实际的,但这需要计算确切的结果(如果我错了,请纠正我)。
因此,我的目标是某种近似。我的想法是使用一个1小时翻滚窗口来产生1小时前平均结果s_1
的流。然后,我会在s_1
上使用持续时间为一周的滑动平均值来计算1周的平均前结果s_2
。除了s_1
和s_2
之外,我还有另一个包含1小时滑动平均结果的流s_3
。然后,我会加入流s_2
和s_3
,并加入元组(t_2, t_3)
,我会发出(t_2 + t_3) / 2
。对于每个平均元组,我还会附加包含元组的最小和最大时间戳。我会使用这些时间戳来防止s_2和s_3元组的重叠。例如:
s_2 tumbling window size 2 (tuples)
s_3 sliding window size 2, interval 1 (tuples)
stream 3 4 9 8 7
time s_2 2_3 out
1 - 3 3
2 - 3.5 3.5
3 3.5 6.5 3.5 the s_3 tuple 6.5 is ignored because min_timestamp(6.5) <= max_timestamp(3.5)
4 3.5 8.5 6 (compute (3.5 + 8.5) / 2
5 6 7.5 6 the s_3 tuple 7.5 is ignored because min_timestamp(7.5) <= max_timestamp(6)
虽然我能够使用Apache Storm,但我无法弄清楚如何使用Spark,因为由于滑动间隔不同,Spark中不允许加入s_2和s_3。
问题#1是:我如何在Spark Streaming中实现它?
问题2:你能想到在流处理系统内有效地长时间计算滑动平均值的更好方法吗?
答案 0 :(得分:2)
有许多策略可以在流上生成具有相当高精度的近似答案。我们使用的一种策略是stratified sampling关于spark中的无限流。 我们在一个名为SnappyData的开源项目中将分层抽样引入Apache Spark。好吧,Spark中缺少的其他一些东西。 SnappyData可以在流上保持统一的随机样本,但允许开发人员选择流中重要的列/维度,从而确保高精度。因此,例如,在您的示例中,确保每分钟或每小时捕获足够的样本。样本作为Spark Dataframe / Column表可见,并且可查询。当执行诸如avg / sum / count / etc之类的聚合查询时,它使用一堆算法来使用一小部分资源和时间来计算答案。
这是在Snappydata中看起来如何的伪代码。
Create sample table MyInfiniteStream on <Stream> options (qcs 'min(timestamp), fraction '0.01')
// Of course, you can use the Dataframe api to do this instead of SQL too.
// your DStream <Stream> is registered with SnappyData
// min(timestamp) tells which columns to use for stratification
// fraction indicates what percentage of the input data to retain in the sample.
然后,您可以在有或没有错误限制的情况下直接对此运行Spark SQL查询。现在好处是你的时间间隔可能非常细微或粗糙。
select avg(myMeasureColumn), dimension d from MyInfiniteStream group by d with Error 0.1
// this would ensure the result is always at least 90% accurate.
select avg(myMeasureColumn), dimension d from MyInfiniteStream where timestamp >x and timestamp < y group by d with Error 0.1
您可以更好地理解这些想法here。 SnappyData与Spark完全兼容。
您也可以尝试直接在Spark中实现,尽管没有规定进行在线采样(即直接在流上),也没有内置算法来计算带置信区间的错误。检查数据集上的“样本”方法。