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

实时计算选型,说白了就是选一把趁手的兵器。我见过不少团队,上来就追最新最火的框架,结果业务跑起来各种水土不服。今天咱们就掰开揉碎,把 Flink、Spark Streaming、Kafka Streams 这三兄弟的底裤都扒干净。

先看一张全景图

下面这张图,是我自己画的技术选型决策树。你跟着它走一遍,基本不会跑偏。

实时计算技术选型决策树 实时计算需求 流批一体 + 状态管理 微批处理 + 生态丰富 轻量级 + Kafka 原生 Flink 精确一次语义 Spark Streaming Structured Streaming Kafka Streams 无外部依赖 适用场景 复杂事件处理 实时数仓 / CDC 适用场景 ETL / 批流混合 机器学习特征工程 适用场景 轻量级流处理 微服务集成 选型核心原则 状态复杂度高 → Flink | 批流混合 → Spark | 轻量集成 → Kafka Streams 团队技术栈、运维成本、延迟要求,三者缺一不可

Flink:真正的实时流处理之王

Flink 的设计哲学,就是「事件来一个处理一个」。它不像 Spark 那样攒一批再算,而是每条数据到了就触发计算。我最早接触 Flink 是在 2018 年,当时做一个金融风控项目,要求毫秒级延迟。Spark Streaming 试了,延迟在秒级,根本扛不住。换了 Flink 之后,延迟直接降到几十毫秒。

核心优势:

  • 真正的流处理:每条数据独立处理,延迟在毫秒级
  • 精确一次语义:端到端的一致性保证,不会丢数据也不会重复
  • 强大的状态管理:内置 RocksDB 状态后端,支持超大状态
  • 事件时间语义:处理乱序数据的能力极强

举个例子,你要统计过去 5 分钟每个用户的点击量。Flink 可以精确地按事件时间开窗口,即使数据延迟到达也能正确处理。Spark Streaming 做这个就有点吃力,因为它默认按处理时间算。

我的经验:如果你要做复杂事件处理(CEP)、实时数仓、CDC 同步,直接选 Flink。别犹豫。我在项目中用 Flink SQL 做过一个实时 ETL 链路,从 MySQL binlog 到 Kafka 再到 ClickHouse,整个链路延迟不到 1 秒。

Spark Streaming:批处理思维的流计算

Spark Streaming 的核心是「微批处理」。它把流数据切成一个个小批次,比如每 2 秒一批,然后对每个批次做批处理计算。说白了,它还是用批处理的思路做流计算。

我记得有个同事问我:「为什么 Spark Streaming 的延迟降不下来?」我告诉他,因为它的架构决定了最小延迟就是批次间隔。你设 500 毫秒,那延迟至少 500 毫秒。Flink 可以做到 10 毫秒以内。

避坑指南:我曾经在一个项目里用 Spark Streaming 做实时推荐,结果发现状态管理特别麻烦。Spark Streaming 的 updateStateByKey 在状态大的时候性能下降很快。后来我们改用了 Flink,状态管理就舒服多了。

不过 Spark Streaming 也有它的优势:

  • 生态丰富:和 Spark SQL、MLlib、GraphX 无缝集成
  • 批流统一:Structured Streaming 让批处理和流处理用同一套 API
  • 社区成熟:文档多,踩坑的人多,解决方案也多

适用场景:

  • ETL 任务,特别是批流混合的场景
  • 机器学习特征工程,需要和 Spark MLlib 配合
  • 对延迟要求不苛刻(秒级可接受)的场景
  • 团队已经深度使用 Spark 技术栈

Kafka Streams:轻量级流处理库

Kafka Streams 和其他两个不一样。它不是一个框架,而是一个 Java 库。你把它当成一个依赖加到项目里,就能直接写流处理逻辑。不需要搭建集群,不需要部署额外的服务。

我第一次用 Kafka Streams 是在一个微服务项目里。当时需要做实时数据清洗,把原始日志转成标准格式。如果用 Flink,还得搭一个 Flink 集群,太重了。Kafka Streams 直接嵌在服务里,几行代码就搞定了。

我的建议:如果你的场景是「从 Kafka 读,处理完写回 Kafka」,而且逻辑不复杂,Kafka Streams 是最佳选择。它和 Kafka 深度集成,天然支持 exactly-once 语义。

但要注意,Kafka Streams 也有短板:

  • 只支持 Kafka:数据源和数据目标都必须是 Kafka
  • 状态管理有限:虽然支持状态存储,但不如 Flink 强大
  • 不适合复杂计算:做简单的过滤、转换、聚合还行,复杂事件处理就吃力了

三兄弟正面硬刚

下面这张表,是我自己整理的对比清单。你选型的时候直接对着看就行。

对比维度 Flink Spark Streaming Kafka Streams
处理模型 真正的流处理 微批处理 流处理(记录级别)
延迟 毫秒级 秒级(取决于批次间隔) 毫秒级
状态管理 强大(RocksDB + 定时快照) 一般(updateStateByKey) 中等(内置状态存储)
精确一次语义 端到端支持 支持(需配置) 支持(Kafka 事务)
部署运维 需要独立集群 需要 Spark 集群 嵌入应用,无额外部署
学习曲线 中等 较低(熟悉 Spark 的话) 低(纯 Java 库)
生态集成 丰富(Flink SQL、CEP、CDC) 非常丰富(Spark 全家桶) 有限(仅 Kafka)
适用场景 复杂事件处理、实时数仓、CDC ETL、批流混合、ML 特征工程 轻量级流处理、微服务集成

选型决策指南

说了这么多,到底怎么选?我给你一个简单的决策流程:

  1. 先看延迟要求:毫秒级必须 Flink 或 Kafka Streams;秒级可以 Spark Streaming
  2. 再看状态复杂度:复杂状态管理(窗口聚合、多流 Join)→ Flink;简单状态 → 三者都行
  3. 然后看数据源:只有 Kafka → Kafka Streams 最轻量;多种数据源 → Flink 或 Spark
  4. 最后看团队:熟悉 Java 微服务 → Kafka Streams;熟悉 Spark → Spark Streaming;愿意学新东西 → Flink

我曾经踩过的坑:有个项目,业务方说「延迟要求不高,秒级就行」。我们选了 Spark Streaming,结果上线后发现业务逻辑里有复杂的多流 Join 和状态聚合。Spark Streaming 做这个特别别扭,最后不得不重构成 Flink。所以,选型的时候一定要把业务逻辑的复杂度考虑进去,别只看延迟指标。

小结

实时计算选型没有银弹。Flink 强在状态管理和低延迟,Spark Streaming 强在生态和批流统一,Kafka Streams 强在轻量和易集成。我的建议是:

  • 新项目、复杂逻辑 → Flink
  • 已有 Spark 技术栈、批流混合 → Spark Streaming
  • 微服务、简单处理、Kafka 原生 → Kafka Streams

选对了框架,后面的事就顺了。选错了,后面全是坑。