实时统计每分钟的PV——Flink的窗口类型怎么选?
先说结论
| 窗口类型 | 原理 | 典型场景 |
|---|---|---|
| 滚动窗口 Tumbling | 固定大小、不重叠、首尾相接 | 每5分钟PV、每小时GMV |
| 滑动窗口 Sliding | 固定大小、有重叠、按步长滑动 | 过去1小时每5分钟统计一次 |
| 会话窗口 Session | 活动间隔超过gap就关闭 | 用户行为会话分析 |
| 全局窗口 Global | 永远不关闭,手动触发 | 自定义触发逻辑 |
先把这段讲顺;面试官追问时,再展开下面的原理和细节。
详细讲解
窗口是Flink流处理的核心抽象。“每5分钟统计一次”“过去1小时的滚动均值”“用户登录后多久没有操作就算一次会话”——这些都是不同的窗口。今天把四种窗口的原理、选型和实战场景讲清楚。
滚动窗口(最常用)
滚动窗口是最简单也最常用的窗口。窗口之间不重叠、不遊漏,每条数据只属于一个窗口。
// 每5分钟统计一次PV
stream.keyBy(e -> e.getPageId())
.window(TumblingEventTimeWindows.of(Time.minutes(5)))
.aggregate(new CountAgg());
// 注意:窗口对齐到整点时刻
// 比如窗口大小5分钟,窗口是 [00:00, 00:05), [00:05, 00:10)...
// 不是从作业启动时间开始算的
滑动窗口(统计趋势用)
滑动窗口有重叠,同一条数据可能属于多个窗口。窗口大小/步长 = 每条数据所属的窗口数。比如窗口1小时、步长5分钟,每条数据属于12个窗口。状态开销比滚动窗口大很多!
// 过去1小时的PV,每5分钟输出一次
stream.keyBy(e -> e.getPageId())
.window(SlidingEventTimeWindows.of(Time.hours(1), Time.minutes(5)))
.aggregate(new CountAgg());
会话窗口(用户行为分析)
会话窗口的大小是动态的——用户活动间隔超过gap就关闭窗口。比如设置gap=30分钟,用户30分钟没有操作就算一次会话结束。
我在元宇宙社交App用会话窗口统计用户的“单次使用时长”和“单次互动次数”,用于分析用户的活跃度和留存。
面试高频追问:窗口的状态开销
面试官经常追问:“滑动窗口和滚动窗口的状态开销有什么区别?”
滚动窗口:每条数据只属于1个窗口,状态开销小。
滑动窗口:每条数据属于“窗口大小/步长”个窗口。窗口1h步长5min = 12个窗口,状态开销是滚动窗口的12倍!
所以生产环境如果用滑动窗口,注意状态大小和Checkpoint时间。如果状态太大可以考虑用“滚动窗口 + 细粒度聚合 + 下游再汇总”代替。
总结
滚动窗口最常用且状态开销小。滑动窗口适合趋势统计但状态开销大。会话窗口适合用户行为分析。面试时能说清楚四种窗口的选型依据和状态开销差异,就很有深度。
下一篇聊一个生产环境很常见的问题:上游Kafka有数据倾斜,某个算子卡住了——Flink数据倾斜怎么解决?
你们生产环境用哪种窗口最多?评论区聊聊~
关注「Wood聊大数据」| 9年大数据老兵,聊技术、聊职场、聊成长