Flink的时间类型和窗口概述,助你进阶Flink,美的java面试流程

本文介绍了流处理中常见的窗口类型,如TumblingWindow、SlidingWindow、SessionWindow、GlobalWindow,以及它们基于processingtime和eventtime的工作原理。重点讨论了窗口操作和各种窗口函数在Java流处理中的使用,包括窗口函数的性能差异和组合应用。最后,提到了Java开发者的学习资源和职业发展建议。
摘要由CSDN通过智能技术生成

按照窗口的Assigner来分,窗口可以分为

Tumbling window, sliding window,session window,global window,custom window

每种窗口又可分别基于processing time和event time,这样的话,窗口的类型严格来说就有很多。

还有一种window叫做count window,依据元素到达的数量进行分配,之后也会提到。

窗口的生命周期开始在第一个属于这个窗口的元素到达的时候,结束于第一个不属于这个窗口的元素到达的时候。

二、窗口的操作


2.1 Tumbling window

固定相同间隔分配窗口,每个窗口之间没有重叠看图一眼明白。

下面的例子定义了每隔3毫秒一个窗口的流:

WindowedStream<MovieRate, Integer, TimeWindow> Rates = rates

.keyBy(MovieRate::getUserId)

.window(TumblingEventTimeWindows.of(Time.milliseconds(3)));

2.2 Sliding Windows

跟上面一样,固定相同间隔分配窗口,只不过每个窗口之间有重叠。窗口重叠的部分如果比窗口小,窗口将会有多个重叠,即一个元素可能被分配到多个窗口里去。

下面的例子给出窗口大小为10毫秒,重叠为5毫秒的流:

WindowedStream<MovieRate, Integer, TimeWindow> Rates = rates

.keyBy(MovieRate::getUserId)

.window(SlidingEventTimeWindows.of(Time.milliseconds(10), Time.milliseconds(5)));

2.3 Session window

这种窗口主要是根据活动的事件进行窗口化,他们通常不重叠,也没有一个固定的开始和结束时间。一个session window关闭通常是由于一段时间没有收到元素。在这种用户交互事件流中,我们首先想到的是将事件聚合到会话窗口中(一段用户持续活跃的周期),由非活跃的间隙分隔开。

// 静态间隔时间

WindowedStream<MovieRate, Integer, TimeWindow> Rates = rates

.keyBy(MovieRate::getUserId)

.window(EventTimeSessionWindows.withGap(Time.milliseconds(10)));

// 动态时间

WindowedStream<MovieRate, Integer, TimeWindow> Rates = rates

.keyBy(MovieRate::getUserId)

.window(EventTimeSessionWindows.withDynamicGap(()));

2.4 Global window

将所有相同keyed的元素分配到一个窗口里。好吧,就这样:

WindowedStream<MovieRate, Integer, GlobalWindow> Rates = rates

.keyBy(MovieRate::getUserId)

.window(GlobalWindows.create());

三、窗口函数


窗口函数就是这四个:ReduceFunction,AggregateFunction,FoldFunction,ProcessWindowFunction。前两个执行得更有效,因为Flink可以增量地聚合每个到达窗口的元素。

Flink必须在调用函数之前在内部缓冲窗口中的所有元素,所以使用ProcessWindowFunction进行操作效率不高。不过ProcessWindowFunction可以跟其他的窗口函数结合使用,其他函数接受增量信息,ProcessWindowFunction接受窗口的元数据。

举一个AggregateFunction的例子吧,下面代码为MovieRate按user分组,且分配5毫秒的Tumbling窗口,返回每个user在窗口内评分的所有分数的平均值。

DataStream<Tuple2<Integer,Double>> Rates = rates

.keyBy(MovieRate::getUserId)

.window(TumblingEventTimeWindows.of(Time.milliseconds(5)))

.aggregate(new AggregateFunction<MovieRate, AverageAccumulator, Tuple2<Integer,Double>>() {

@Override

public AverageAccumulator createAccumulator() {

return new AverageAccumulator();

}

@Override

public AverageAccumulator add(MovieRate movieRate, AverageAccumulator acc) {

acc.userId = movieRate.userId;

acc.sum += movieRate.rate;

acc.count++;

return acc;

}

@Override

public Tuple2<Integer,Double> getResult(AverageAccumulator acc) {

return Tuple2.of(acc.userId, acc.sum/(double)acc.count);

}

@Override

public AverageAccumulator merge(AverageAccumulator acc0, AverageAccumulator acc1) {

acc0.count += acc1.count;

acc0.sum += acc1.sum;

return acc0;

}

});

public static class AverageAccumulator{

int userId;

int count;

double sum;

}

以下是部分输出:

1> (44,3.0)

4> (96,0.5)

2> (51,0.5)

3> (90,2.75)

看上面的代码,会发现add()函数特别生硬,因为我们想返回Tuple2<Integer, Double>类型,即Integer为key,但AggregateFunction似乎没有提供这个机制可以让AverageAccumulator的构造函数提供参数。所以,这里引入ProcessWindowFunction与AggregateFunction的结合版,AggregateFunction进行增量叠加,当窗口关闭时,ProcessWindowFunction将会被提供AggregateFunction返回的结果,进行Tuple封装:

DataStream<Tuple2<Integer,Double>> Rates = rates

.keyBy(MovieRate::getUserId)

.window(TumblingEventTimeWindows.of(Time.milliseconds(5)))

.aggregate(new MyAggregateFunction(), new MyProcessWindowFunction());

public static class MyAggregateFunction implements AggregateFunction<MovieRate, AverageAccumulator, Double> {

@Override

public AverageAccumulator createAccumulator() {

return new AverageAccumulator();

}

@Override

public AverageAccumulator add(MovieRate movieRate, AverageAccumulator acc) {

acc.sum += movieRate.rate;

acc.count++;

return acc;

}

@Override

public Double getResult(AverageAccumulator acc) {

return acc.sum/(double)acc.count;

}

@Override

public AverageAccumulator merge(AverageAccumulator acc0, AverageAccumulator acc1) {

acc0.count += acc1.count;

acc0.sum += acc1.sum;

return acc0;

}

}

public static class MyProcessWindowFunction extends

ProcessWindowFunction<Double, Tuple2<Integer, Double>, Integer, TimeWindow> {

@Override

public void process(Integer key,

Context context,

Iterable results,

Collector<Tuple2<Integer, Double>> out) throws Exception {

Double result = results.iterator().next();

out.collect(new Tuple2<>(key, result));

}

}

public static class AverageAccumulator{

int count;

double sum;

}

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Java)
img

结语

小编也是很有感触,如果一直都是在中小公司,没有接触过大型的互联网架构设计的话,只靠自己看书去提升可能一辈子都很难达到高级架构师的技术和认知高度。向厉害的人去学习是最有效减少时间摸索、精力浪费的方式。

我们选择的这个行业就一直要持续的学习,又很吃青春饭。

虽然大家可能经常见到说程序员年薪几十万,但这样的人毕竟不是大部份,要么是有名校光环,要么是在阿里华为这样的大企业。年龄一大,更有可能被裁。

送给每一位想学习Java小伙伴,用来提升自己。

在这里插入图片描述

本文到这里就结束了,喜欢的朋友可以帮忙点赞和评论一下,感谢支持!
有帮助,可以添加V获取:vip1024b (备注Java)**
[外链图片转存中…(img-CKcivEmp-1711884779609)]

结语

小编也是很有感触,如果一直都是在中小公司,没有接触过大型的互联网架构设计的话,只靠自己看书去提升可能一辈子都很难达到高级架构师的技术和认知高度。向厉害的人去学习是最有效减少时间摸索、精力浪费的方式。

我们选择的这个行业就一直要持续的学习,又很吃青春饭。

虽然大家可能经常见到说程序员年薪几十万,但这样的人毕竟不是大部份,要么是有名校光环,要么是在阿里华为这样的大企业。年龄一大,更有可能被裁。

送给每一位想学习Java小伙伴,用来提升自己。

[外链图片转存中…(img-BaZaupEy-1711884779609)]

本文到这里就结束了,喜欢的朋友可以帮忙点赞和评论一下,感谢支持!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值