实时计算技术选型:Flink vs Spark Streaming vs Kafka Streams

做实时特征资产化,第一步就是选计算引擎。选错了,后面全是坑。

我见过不少团队,上来就拍脑袋选 Flink,理由是“大家都在用”。结果业务场景只是简单的消息过滤,Kafka Streams 几十行代码就能搞定,非得上个 Flink 集群,运维成本翻了好几倍。也见过迷信 Spark Streaming 的,处理秒级延迟的指标计算,结果反压调优调了一个月。

所以这一节,咱们把三个主流引擎掰开揉碎讲清楚。不吹不黑,只看场景。

三驾马车:核心定位速览

先给个直观的对比。我习惯用一张表来快速对齐认知:

维度 Apache Flink Spark Streaming Kafka Streams
计算模型 真正的流式计算(逐条处理) 微批次(Micro-Batch) 流式计算(Record-at-a-time)
延迟 亚秒级(毫秒) 秒级(默认批次间隔) 亚秒级(毫秒)
状态管理 内置 RocksDB + 定时快照 依赖外部存储(Redis/HBase) 内置 RocksDB + 变更日志 Topic
语义保证 Exactly-Once(端到端) Exactly-Once(微批次内) Exactly-Once(需配合幂等生产者)
部署模式 独立集群 / YARN / K8s 独立集群 / YARN / K8s 内嵌库(无需集群)
学习曲线 中等偏难 中等 较易

这张表看下来,你可能会问:那是不是 Flink 最好?别急,咱们一个一个拆。

Apache Flink:实时特征资产化的主力军

我个人最常用 Flink 做特征工程。为什么?因为它把“流”这件事做到了骨子里。

Flink 的核心是 DataStream API。每条数据进来,立即触发计算,不攒批。这在做实时特征时特别重要——你想想看,用户点击行为发生的那一瞬间,特征就要更新,等不了那几秒的批次间隔。

Flink 在特征资产化中的典型场景:

  • 复杂事件处理(CEP):用户浏览序列 -> 实时拼接成会话特征
  • 多流 Join:用户画像流 + 实时行为流 -> 生成 enriched 特征
  • 窗口聚合:5 分钟滑动窗口内的点击率、转化率特征
  • 状态回溯:基于历史状态的实时特征计算(如用户累计消费金额)

我记得有一次做风控特征,需要把用户过去 30 天的交易行为做滑动窗口聚合。Flink 的 SlidingEventTimeWindows 配合 AggregateFunction,代码量不到 100 行,状态管理自动由 RocksDB 搞定。换成 Spark Streaming,你得自己维护一个外部状态存储,还要处理状态过期的问题。

不过 Flink 也有它的痛点。部署运维成本高,调优参数多。我见过新手把 checkpoint间隔 设成 1 秒,结果集群频繁快照,吞吐直接腰斩。嗯,这里要注意:checkpoint 间隔建议 30 秒以上,除非你的状态极小。

Spark Streaming:批处理思维的延续

Spark Streaming 本质上是“微批次”。它把流切成一堆小批次,每个批次用 Spark 的批处理引擎去算。

这种设计有好有坏。好处是:如果你团队已经熟悉 Spark 批处理,迁移成本很低。坏处是:延迟天然受批次间隔限制。

我做过一个实验:同样一个简单的计数任务,Flink 延迟在 100ms 以内,Spark Streaming 设成 1 秒批次间隔,延迟在 1.2 秒左右。如果你的业务能接受秒级延迟,Spark Streaming 完全够用。

什么时候选 Spark Streaming?

  • 你已经有成熟的 Spark 批处理 pipeline,不想引入新引擎
  • 特征计算以 T+1 或小时级为主,实时只是辅助
  • 需要和 Spark MLlib 做模型推理集成
  • 团队 Spark 能力强,Flink 经验不足

但要注意一个坑:反压。我曾经在一个项目中,用 Spark Streaming 处理高峰期的用户点击流,数据量突然暴涨,批次处理时间超过了批次间隔,导致背压堆积。调了 spark.streaming.backpressure.enabled 才稳住。而 Flink 的反压机制是天然的,不需要额外配置。

Kafka Streams:轻量级的选择

Kafka Streams 是个异类。它不是一个集群,而是一个 Java 库。你把它打成 jar 包,嵌在你的应用里就能跑。

它的核心思想是:流就是表,表就是流。通过 KTable 和 KStream 的转换,实现状态化计算。

我特别喜欢 Kafka Streams 的一点是:部署简单。不需要运维一个 Flink 或 Spark 集群,只需要一个 Kafka 集群就够了。对于中小团队来说,这能省下大量运维精力。

Kafka Streams 的局限性:

  • 只能消费 Kafka 数据源,无法直接对接其他系统(如 MySQL CDC)
  • 复杂窗口和 Join 能力弱于 Flink
  • 状态大小受限于本地磁盘,不适合超大规模状态
  • 调试和监控不如 Flink 方便

我曾经在一个 IoT 项目中,用 Kafka Streams 做设备状态的实时特征计算。每条设备上报数据,通过 groupByKey + reduce 聚合出最近 10 分钟的平均温度、最大电压等特征。代码简洁,部署就是一个 Spring Boot 应用,运维成本几乎为零。

但如果你要做跨多个 Topic 的复杂 Join,或者需要事件时间语义的精确窗口,Kafka Streams 就有点吃力了。这时候还是 Flink 更合适。

选型决策框架:一张图说清楚

下面这张图是我自己总结的选型决策流程,每次做技术选型我都会拿出来对照一下:

实时计算引擎选型决策流程图 实时计算引擎选型决策流程 业务需求输入 延迟要求:亚秒级 vs 秒级? 亚秒级 秒级 仅 Kafka 数据源? Kafka Streams 否 Apache Flink 已有 Spark 生态? Spark Streaming 否 选型建议 • 亚秒级 + 多数据源 → Flink(特征资产化首选) • 亚秒级 + 仅 Kafka → Kafka Streams(轻量高效) • 秒级 + 已有 Spark → Spark Streaming(平滑迁移) • 秒级 + 无历史包袱 → Flink(面向未来)

实战中的选型建议

说了这么多,到底怎么选?我给出三个典型场景的推荐:

场景一:实时风控特征计算

延迟要求:毫秒级。数据源:Kafka + MySQL CDC。状态:大(用户历史行为)。

推荐:Flink。原因:事件时间语义、Exactly-Once、大状态管理。

场景二:实时监控指标聚合

延迟要求:秒级。数据源:Kafka。状态:小(窗口聚合)。

推荐:Kafka Streams。原因:部署简单,运维成本低。

场景三:实时特征 + 离线批处理一体化

延迟要求:秒级。数据源:Kafka + HDFS。状态:中等。

推荐:Spark Streaming。原因:与 Spark 批处理共享代码和集群。

最后说一句:没有银弹。我见过用 Flink 做简单 ETL 的,也见过用 Kafka Streams 做复杂 CEP 的。选型不是比谁更牛,而是比谁更合适。你的团队擅长什么、你的运维能力有多强、你的业务容忍多高的延迟——这些才是决策的关键。