窗口:在一段时间语义下的时间范围,可以是分钟、小时、甚至是天、月等。基于一段时间范围内做的数据统计、PV 、UV等。一般窗口都是结合窗口函数进行统计后输出一个结果。
窗口的分类
- 滚动窗口 (TumblingEventTimeWindows)
滚动时间窗口是按照事件时间或者处理时间对到达的流数据进行开窗处理,一个事件只会被分配到一个窗口,在事件时间、滚动窗口下,一个时刻由于设置了WaterMark延迟,同一时刻可能会到达多个窗口,但是一条事件数据只会被分配到一个窗口。
- 滑动窗口(SlidingEventTimeWindows)
滑动窗口不同于滚动窗口,滑动窗口可以每间隔一段时间之后开启新的窗口,开启了滑动窗口的windowedStream一个时间可以被分配到多个窗口。例如滑动窗口范围是每10秒一个窗口范围,而每隔固定的步长时间段后就会开启新的窗口,例如窗口范围是10s,步长是2s,那就是每2秒就会开启一个新窗口、每2秒也会关闭一个窗口。
0-10,2-12,4-14,6-16,8-18,10-20…。
窗口函数
- reduce归约函数
reduce归约函数就是ReduceFunction,实现ReduceFunction的窗口需要基于KeyedStream,也就是说必须先将DataStream转换为KeyedStream,再基于KeyedStream开窗。
.window(SlidingEventTimeWindows.of(Time.of(5, TimeUnit.SECONDS),Time.of(2,TimeUnit.SECONDS)))
.reduce(new ReduceFunction<Tuple2<String, Integer>>() {
@Override
public Tuple2<String, Integer> reduce(Tuple2<String, Integer> stringIntegerTuple2, Tuple2<String, Integer> t1) throws Exception {
return null;
}
})
reduce会将到达的数据执行reduce方法,窗口关窗后,也只能计算出最终的一个Reduce归约类型。
- aggregate 聚合函数
aggregate比reduceAPI更加强大,在aggregate API 中,提供了三个泛型,分别是事件类型,累加器类型,以及最终输出类型。泛型的作用就是类型参数化,包括方法返回值类型,属性类型,方法参数类型 都可以实现参数化,如果不实现参数化,则默认所有的泛型类型都是Object类型,所有方法都需要强转,如果使用了泛型,就给创建的实例明确了参数类型,后续该实例当作其他参数传递时也明确了参数类型,一旦明确了参数类型,编译器就会判断后续的类型是否兼容,例如 lambda表达式,方法引用,泛型通配符,参数传递等 编译器都会自动推断。 定义了泛型而不去实现默认就是Object类型,一般的泛型类都不会针对参数去调用泛型参数方法,而是当作数据处理使用,例如 Map List 等。
@PublicEvolving
public interface AggregateFunction<IN, ACC, OUT> extends Function, Serializable {
ACC createAccumulator();
ACC add(IN var1, ACC var2);
OUT getResult(ACC var1);
ACC merge(ACC var1, ACC var2);
}
- createAccumulator : 创建累加器,在新窗口创建的时候执行。
- add :窗口内每来一个数据就进行回调的方法。
- getResult : 窗口结束时进行的 最终计算方法,输出最终的out泛型类型数据。
- 使用aggregate 实现滚动窗口单位时间内的最大访问用户统计
public class WindowTest {
public static void main(String[] args) throws Exception {
StreamExecutionEnvironment env = Env.getEnv();
SingleOutputStreamOperator<Event> dataStream = Env.getDataStream(env);
WindowedStream<Event, Boolean, TimeWindow> windowedStream = dataStream.keyBy(k -> true)
// .window(TumblingEventTimeWindows.of(Time.seconds(10)));<