实时计算技术选型:Flink vs Spark Streaming vs Kafka Streams
实时计算选型,说白了就是选一把趁手的兵器。我见过不少团队,上来就追最新最火的框架,结果业务跑起来各种水土不服。今天咱们就掰开揉碎,把 Flink、Spark Streaming、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 特征工程 | 轻量级流处理、微服务集成 |
选型决策指南
说了这么多,到底怎么选?我给你一个简单的决策流程:
- 先看延迟要求:毫秒级必须 Flink 或 Kafka Streams;秒级可以 Spark Streaming
- 再看状态复杂度:复杂状态管理(窗口聚合、多流 Join)→ Flink;简单状态 → 三者都行
- 然后看数据源:只有 Kafka → Kafka Streams 最轻量;多种数据源 → Flink 或 Spark
- 最后看团队:熟悉 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
选对了框架,后面的事就顺了。选错了,后面全是坑。