SparkStreaming中的窗口操作
Spark Streaming流式计算框架同样提供了窗口操作,允许在窗口上应用各种转换函数;原理如图所示
此图描述的是一个滑动跳跃窗口
使用窗口必须指定两个参数:
- 窗口长度 : window length 窗口的实际长度(上图,窗口的长度为3个时间单位)
- 滑动步长: sliding interval 滑动的步长或者间距(上图,窗口滑动的步长为2个时间内容)
注:
- 如果需要定义翻滚窗口,
窗口长度=滑动步长
即可- 会话窗口不支持
- 必须进行有状态的计算
下面我们分析一下reduceByKeyAndWindow的两个版本的区别
- reduceByKeyAndWindow(func, windowLength, slideInterval, [numTasks])
- reduceByKeyAndWindow(func, invFunc, windowLength, slideInterval, [numTasks]) 更为高效的reduceByKeyAndWindow操作
原因:
这两个方法都是根据key对value进行reduce操作,并且这两个方法的操作结果都是一致的,区别是效率不同,后面的方法效率更高;
- 第一种方法:累积计算(窗口内微批的结果累积)
- 第二种方法:增量式计算(上一个窗口计算结果 + 当前窗口新增元素-上一个窗口的过期数据=当前窗口的计算结果)
原理剖析:
DStream:10 9 8 7 6 5 4 3 2 1
MicroBatch: b1: 1 b2: 2 b3: 3 …
窗口计算: length 5 step 3
W1: 1 2 3 4 5
W2: 4 5 6 7 8
W3: 7 8 9 10 11
==========================================
第一种方法:reduceByKeyAndWindow 累积计算w1: 1 + 2 + 3 + 4 + 5 = 15 (计算5次)
w2: 4 + 5 + 6 + 7 + 8 = 30 (计算5次)
w3: …第二种方法:reduceByKeyAndWindow 增量式计算 上一个窗口的计算结果 + 当前窗口的新增数据 - 上一个窗口的过期数据
w1: 0 + 1 + 2 + 3 + 4 + 5 - 0 = 15 (计算6次)
w2: 15 + 6 + 7 + 8 - 1 - 2-3 = 30 (计算6次)
w3: 30 +9 + 10 +11 -4 -5-6 = …
为什么说第二种方法的效率比较高呢?
体现:窗口的长度比较大 而滑动的步长比较小
长度:100s 步长:1
w1: 1 - 100
w2: 2 - 101
w3: 3 - 102
=======================================
全量式计算:
w1:1 + 2 + 3 + 4 … 100 100次
w2: 2+ 3 + 4 + 5 …101增量式计算:
w1: 1+ 2 + 3 + 100
w2: 5050 + 101 -1 = 当前窗口的结果 2
结论:窗口的重合比较多建议使用第二个高效方法,窗口的重合数据较少使用第一个
package window.transformation
import org.apache.spark.SparkConf
import org.apache.spark.streaming.{
Seconds, StreamingContext}
/**
* 测试窗口的转换函数(6个)
*/
object TransformationOnWindow {
def main(args: Array[