Window Operations
Spark Streaming还提供了窗口计算,可让你在数据的滑动窗口上应用转换。下图说明了此滑动窗口。
如图所示,每当窗口在源DStream上滑动时,落入窗口内的源RDD就会合并并且对其进行操作,以生成窗口DStream的RDD。在上图中,该操作将应用于数据的最后3个时间单位,并以2个时间间隔单位滑动。这说明任何窗口操作都需要制定两个参数。
- 窗口长度-窗口的持续时间(3倍时间)
- 滑动间隔-进行窗口操作的间隔(2倍时间)
注意: 这两个参数必须是源DStream的批处理间隔
的倍数,因为对于DStream而言,微批是原子性的最小处理单位。通常在流计算中,如果窗口长度=滑动间隔
称该窗口为滚动窗口没有元素重叠;如果窗口长度>滑动间隔
称这个窗口为滑动窗口存在元素重叠;一般情况下所有的流的窗口长度>=滑动间隔
,因为如果小于滑动间隔,会有数据的遗漏。
一些常见的窗口操作如下。所有这些操作均采用上述两个参数windowLength
和slideInterval
。
window(windowLength,slideInterval)
val lines = ssc.socketTextStream("train",9999)
lines.flatMap(line=>line.split(" "))
.map((_,1))
//参数2如果设置为2,则2秒钟打印一次,打印的长度为批处理时间的2倍。
.window(Seconds(2),Seconds(1))
.reduceByKey(_+_)
.print()
这两个Seconds(2),Seconds(1)与DStream每秒为一批中的Seconds不一样。前两个仅仅是针对批的个数设置的。即窗口长度为2倍的批次时间,间隔数为1倍的批次时间。
countByWindow(windowLength,slideInterval)
val lines = ssc.socketTextStream("train",9999)
lines.flatMap(line=>line.split(" "))
.map((_,1))
.countByWindow(Seconds(2),Seconds(1))
.print()
相当于先window然后使用count算子
reduceByWindow(func,windowLength,slideInterval)
val lines = ssc.socketTextStream("train",9999)
lines.flatMap(line=>line.split(" "))
.reduceByWindow(_+"|"+_,Seconds(2),Seconds(1))
.print()
相当于先window然后使用reduce算子
reduceByKeyAndWindow(func,windowLength,slideInterval,[numTasks])
val lines = ssc.socketTextStream("train", 9999)
lines.flatMap(line => line.split(" "))
.map(word=>(word,1))
.reduceByKeyAndWindow((value: Int, value1:Int) => value + value1,Seconds(2),Seconds(2))
.print()
相当于先window然后使用reduceByKey算子
reduceByKeyAndWindow(func,invFunc,windowLength,slideInterval,[numTasks])
val lines = ssc.socketTextStream("train", 9999)
lines.flatMap(line => line.split(" "))
.map(word=>(word,1))
.reduceByKeyAndWindow(
(v1,v2)=>v1+v2, //加上新移入元素
(v1,v2)=>v1-v2, //减去移除元素
Seconds(2),
Seconds(1),
filterFunc = t=>t._2 >0 //过滤掉值=0元素
)
.print()
必须重复元素过半,使用以上方法效率高。