Spark Streaming窗口
以上的图描述的是一个滑动(sliding)窗口:
- window size: 3个时间单位
- slide interval: 2个时间时间
Tumbling(翻滚)窗口
Sliding(滑动)窗口
窗口操作函数
countByWindow(windowLength, slideInterval)
统计每一个窗口中,元素的个数
// 必须设置检查点目录
ssc.checkpoint("hdfs://SparkOnStandalone:9000/checkpoint")
ds
//.countByWindow(Seconds(10), Seconds(3)) // 滑动窗口 数据有可能同时属于多个窗口
// w1: 00~10
// w2: 03~13
// w3: 06~16
.countByWindow(Seconds(10), Seconds(10)) // 翻滚窗口 不会重合
// w1: 00~10
// w2: 10~20
.print()
reduceByWindow(func, windowLength, slideInterval)
将窗口内的数据,进行聚合(计算)操作
ds
.map(line => line.toInt) // "1" ---> 1
.reduceByWindow(_ * _, Seconds(10), Seconds(10))
.print()
reduceByKeyAndWindow(func, windowLength, slideInterval, [numTasks])
对窗口内的数据,按照key进行reduce函数计算
ds
.map(line => (line, 1))
.reduceByKeyAndWindow((v1: Int, v2: Int) => v1 + v2, Seconds(10), Seconds(10))
.print()
reduceByKeyAndWindow(func, invFunc, windowLength, slideInterval, [numTasks])
更高效率的reduceByKeyAndWindow方法
原因: 计算时,会使用上一窗口的计算结果 + 当前窗口的新增元素 - 上一窗口的过期数据
第一种方法: reduceByKeyAndWindow(*func*, *windowLength*, *slideInterval*, [*numTasks*])
假如: 滑动窗口 大小 5s 步长2s 聚合操作:(v1: Int, v2: Int) => v1 + v2
10 9 8 7 6 5 4 3 2 1 0
w1 = 0~5 0+1+2+3+4 = 10
w2 = 2~7 2+3+4+5+6 = 20
w3 = 4~9 4+5+6+7+8 = 30
第二种方法 reduceByKeyAndWindow(*func*, *invFunc*, *windowLength*, *slideInterval*, [*numTasks*])
计算方法规则: 上一个窗口聚合结果 + 当前窗口增量元素 - 上一个窗口的过期数据
10 9 8 7 6 5 4 3 2 1 0
w1 = 0~5 0+1+2+3+4 = 0 + 10 - 0
w2 = 2~7 10 + 5 + 6 - 1 - 0 = 20
w3 = 4~9 20 + 7 + 8 - 2 - 3 = 30
大小 100 s 步长 1s
w1: 0~100 0 +1 +2 ...+100 = 5050
w2: 1~101 1+ 2 +3 ...+101 = 5151
w1: 0~100 0 +1 +2 ...+100 = 5050
w2:1~101 5050+101-0 = 5151
// 必须设置检查点目录
ssc.checkpoint("hdfs://SparkOnStandalone:9000/checkpoint2")
ds
.map(line => (line, 1))
.reduceByKeyAndWindow((v1: Int, v2: Int) => v1 + v2, (v1: Int, v2: Int) => v1 - v2, Seconds(5), Seconds(2))
.print()
countByValueAndWindow(windowLength, slideInterval, [numTasks])
ssc.checkpoint("hdfs://SparkOnStandalone:9000/checkpoint3")
ds
.countByValueAndWindow(Seconds(5),Seconds(5))
.print()