面试题:如何用Flink实时计算QPS
Flink 实时计算 QPS 面试题
题目:
假设某互联网应用日活用户 100 万,每天产生 1 亿条数据(日志/事件),要求使用 Apache Flink 实现实时计算系统的 QPS(Queries Per Second),并考虑以下需求:
实时统计当前 QPS(每秒请求数),并输出到监控系统(如 Prometheus、Kafka、MySQL 等)。
处理数据倾斜,某些 key(如热门用户或接口)可能产生大量数据,如何优化?
保证 Exactly-Once 语义,确保 QPS 计算不丢不重。
应对高峰流量,假设瞬时 QPS 可能达到 10,000,如何保证 Flink 作业的稳定性和低延迟?
问题:
请设计 Flink 作业的数据流(Source → Transformation → Sink),并说明关键算子(如
window
、keyBy
、aggregate
)的作用。如何实现 QPS 的滑动窗口(如每 1s 计算一次最近 10s 的 QPS)?
如果某些 key 的数据量远高于其他 key(数据倾斜),你会如何优化?
如何保证 Exactly-Once 语义?请结合 Checkpoint 和 StateBackend 说明。
如果 QPS 突增导致反压(Backpressure),你会如何调整 Flink 作业配置?
考察点
✅ Flink 核心概念:Window、KeyedStream、State、Checkpoint
✅ 性能优化:数据倾斜处理、反压调优
✅ 容错机制:Exactly-Once 实现方式
✅ 生产经验:监控、Sink 适配、资源分配
参考答案(简要版)
1. Flink 作业设计
DataStream<LogEvent> source = env.addSource(new KafkaSource<>(...)); // 从 Kafka 消费日志
DataStream<Tuple2<String, Long>> mapped = source .map(event -> Tuple2.of(event.getEndpoint(), 1L)) // 转换为 (endpoint, 1) .returns(Types.TUPLE(Types.STRING, Types.LONG)); // 按接口名分组,计算每 10s 滑动窗口(每 1s 输出一次)
DataStream<QpsResult> qpsStream = mapped .keyBy(t -> t.f0) // 按接口分组(可能数据倾斜) .window(SlidingProcessingTimeWindows.of(Time.seconds(10), Time.seconds(1))) .aggregate(new QpsAggregator()) // 自定义聚合函数 .addSink(new PrometheusSink()); // 输出到监控系统
2. 数据倾斜优化
方案 1:加随机前缀,如
hot_key
→hot_key_1
,hot_key_2
,聚合后再合并。方案 2:使用
rebalance()
强制均匀分发,牺牲局部有序性。
3. Exactly-Once 保证
Checkpoint 机制:开启
enableCheckpointing(5000)
,设置CheckpointingMode.EXACTLY_ONCE
。StateBackend:使用
RocksDBStateBackend
(大状态)或FsStateBackend
(低延迟)。Sink 端:Kafka 事务 / 幂等写入(如 MySQL 用
INSERT ON DUPLICATE KEY UPDATE
)。
4. 反压调优
增加并行度:
setParallelism(4)
分散负载。调整缓冲区:
taskmanager.network.memory.floating-buffers-per-gate
。启用 RocksDB 本地 SSD:减少 State 访问延迟。
进阶问题:
如果 QPS 计算需要区分成功/失败请求(如 HTTP 200 vs 500),如何修改?
如何用 Flink SQL 实现相同的 QPS 计算?
(面试者可选择继续深入讨论~)