技术选型概览:Flink、Spark Streaming、Kafka Streams 的简单对比

说实话,我刚入行那会儿,也被这三个框架搞得头晕。Flink、Spark Streaming、Kafka Streams,名字都带个「流」,到底选哪个?

我见过不少团队,技术选型时只看热度。哪个火用哪个。结果呢?项目做到一半发现根本不适合自己的场景,改又改不动,硬着头皮上线,运维成本高得吓人。

今天咱们就把这三兄弟拉出来遛遛。不搞虚的,直接看它们各自的看家本领,以及——为什么 Flink 成了流批一体的事实标准。

先看一张全景图

下面这张图,是我自己总结的。它把三个框架的核心定位、处理模式、以及适用场景都串起来了。你盯着看两分钟,心里就有谱了。

流处理框架全景对比 Apache Flink Spark Streaming Kafka Streams 处理模式 处理模式 处理模式 真正的逐条事件驱动 微批次(Micro-batch) 事件驱动 + 状态存储 流批一体 流批一体 流批一体 原生支持 需额外配置 不支持 延迟 延迟 延迟 毫秒级 秒级(批次间隔) 毫秒级 适用场景总结 Flink:实时数仓、风控、ETL、复杂事件处理 Spark Streaming:与Spark生态集成、离线+准实时混合场景 Kafka Streams:轻量级、Kafka原生、简单流处理

三个框架的核心差异

咱们一个一个说。先看 Spark Streaming。

Spark Streaming:微批次的「伪流」

Spark Streaming 的核心思想,是把连续不断的流数据切成一个个小批次。比如每 5 秒切一刀,然后把这 5 秒内的数据当成一个「小批次」去处理。

这样做的好处很明显——它复用了 Spark 的批处理引擎。你写批处理的代码,稍微改改就能跑流。但问题也出在这里。

它不是真正的流处理。 数据到了之后,得等当前批次结束才能处理。延迟至少是一个批次间隔。我见过有人把批次间隔设到 500 毫秒,结果集群压力巨大,吞吐反而上不去。

另外,Spark Streaming 的流批一体是后来补的。它用了一个叫 Structured Streaming 的模块,底层还是微批次。虽然加了 Continuous Processing 模式,但生产环境用得少,坑也不少。

我的经验: 如果你的团队已经重度使用 Spark 做离线,且对延迟要求不高(秒级可以接受),Spark Streaming 是个稳妥的选择。但别指望它能做到真正的毫秒级。

Kafka Streams:轻量但局限

Kafka Streams 是个有意思的东西。它不是一个独立的集群,而是一个 Java 库。你写代码的时候引入依赖,跑起来就是一个流处理应用。

它的优势在于轻量和与 Kafka 的无缝集成。状态存储、容错、Exactly-Once 语义,这些它都有。而且延迟很低,毫秒级。

但它的短板也很明显——不支持批处理。你没法用 Kafka Streams 去读一个 HDFS 上的历史文件做批量计算。它只能处理 Kafka 里的实时数据。

这就意味着,如果你要做流批一体,Kafka Streams 直接出局。它连「批」的门都没摸到。

注意: 我曾经在一个项目里尝试用 Kafka Streams 做实时聚合,后来发现需要回溯 7 天的历史数据做对比。结果呢?只能再搭一套 Flink 作业去读 Kafka 的日志。架构变得不伦不类。

Flink:真正的流批一体

Flink 的设计哲学跟前面两个完全不同。它从底层就把「流」当作一等公民。批处理?在 Flink 眼里,批就是「有界流」。数据有尽头而已,处理逻辑一模一样。

这句话你细品。这意味着什么?

  • 同一套 API:你写流作业的代码,换个输入源就能跑批。反之亦然。
  • 同一套运行时:流和批共享同一个执行引擎,没有两套底层。
  • 同一套语义:状态、时间、容错,流和批的行为完全一致。

我举个例子。你在 Flink 里写一个 DataStream 的 keyBy().window().sum(),这个代码既能跑在实时数据上,也能跑在离线文件上。你只需要把 KafkaSource 换成 FileSource 就行。

Spark Streaming 能做到吗?不能。它的批处理用 DataFrame,流处理用 DStream 或 Streaming DataFrame,虽然越来越像,但底层还是两套东西。

核心结论: Flink 的流批一体不是「拼凑」出来的,而是「生来如此」。它的底层架构决定了它既能处理无界流,也能处理有界流,且行为完全一致。

一张表看清差异

我把关键维度整理成了表格。你保存下来,选型时直接对照。

对比维度 Flink Spark Streaming Kafka Streams
处理模式 事件驱动(逐条) 微批次 事件驱动
延迟 毫秒级 秒级(取决于批次间隔) 毫秒级
流批一体 原生支持 需 Structured Streaming 不支持
状态管理 内置状态后端(RocksDB/Heap) 依赖外部存储 内置状态存储
Exactly-Once 端到端支持 支持(需配置) 支持
生态集成 Kafka、HDFS、JDBC、ES 等 Spark 生态(Hive、MLlib 等) 仅 Kafka
学习曲线 中等 较低(有 Spark 基础) 低(Java 库)
适用场景 实时数仓、风控、ETL、复杂事件 准实时、与离线 Spark 混合 轻量级 Kafka 流处理

为什么 Flink 是流批一体的首选?

说白了,就三个字——一致性。

你想想看,一个系统里,流和批用两套代码、两套引擎、两套运维方式,这本身就是灾难。数据对不上怎么办?口径不一致怎么办?出了问题查哪个系统?

Flink 把这个问题从根本上解决了。它让你用一套代码、一套引擎、一套运维,同时覆盖流和批。这不是锦上添花,而是架构层面的降维打击。

我记得有一次,业务方要求把实时报表和离线报表做对比。以前的做法是:实时走 Flink,离线走 Hive,两边口径经常对不上,每次都要花半天排查。后来我们把离线也迁到了 Flink,用同一套 SQL 逻辑跑批。结果呢?对比报表一次通过,再也没扯过皮。

这就是流批一体的价值。不是技术炫技,而是实实在在的降本增效。

我的建议: 如果你正在从零搭建数据平台,或者准备做技术架构升级,直接选 Flink。别在 Spark Streaming 和 Kafka Streams 上纠结。未来两三年,流批一体是趋势,Flink 是这条路上最成熟的选项。

什么时候选另外两个?

当然,Flink 不是万能的。我也得说句公道话。

  • 选 Spark Streaming:如果你的团队全是 Spark 背景,且对延迟不敏感(秒级够用),Spark Streaming 可以让你快速上手,复用现有 Spark 集群。
  • 选 Kafka Streams:如果你只需要在 Kafka 内部做简单的过滤、转换、聚合,不想引入额外的集群,Kafka Streams 是最轻量的方案。

但记住一点:这两个方案都做不了真正的流批一体。一旦你的业务需要同时处理历史和实时数据,或者需要流批口径一致,Flink 是唯一的选择。

嗯,技术选型这事儿,没有银弹。但如果你问我个人习惯,我会说:能上 Flink 就上 Flink。少折腾,多睡觉。