2、实时计算技术选型:Flink、Spark Streaming、Kafka Streams 对比与选型策略
实时计算选型,是每个做实时数据产品的人都要过的第一道坎。我见过不少团队,技术选型时只看热度,结果后面踩坑踩到怀疑人生。说白了,没有最好的引擎,只有最适合你场景的引擎。
今天我就把 Flink、Spark Streaming、Kafka Streams 这三兄弟掰开揉碎讲清楚。我会结合自己这些年踩过的坑,给你一套可落地的选型策略。
核心观点:选型不是比谁功能多,而是看你的业务场景、团队能力和运维成本三者之间的平衡点在哪里。
2.1 三驾马车:各自的核心定位
先给个全景图。我习惯用一张图来理解这三者的关系:
2.2 核心差异:从架构到语义
这三者的本质区别,在于它们对"流"的理解完全不同。我刚开始接触时也迷糊过,后来发现抓住三个维度就够了:处理模型、状态管理、一致性语义。
| 对比维度 | Flink | Spark Streaming | Kafka Streams |
|---|---|---|---|
| 处理模型 | 真正的流式处理(逐条) | 微批处理(Mini-Batch) | 流式处理(记录级) |
| 延迟 | 亚秒级(< 100ms) | 秒级(通常 1-10s) | 毫秒级(< 10ms) |
| 状态管理 | 内置状态后端(RocksDB/Heap) | 依赖外部存储(Redis/HBase) | 内置状态存储(RocksDB) |
| 一致性语义 | 精确一次(Exactly-Once) | 精确一次(依赖外部事务) | 至少一次(At-Least-Once) |
| 部署方式 | 独立集群 / YARN / K8s | Spark 集群 | 嵌入应用(无独立集群) |
| 编程语言 | Java / Scala / Python | Scala / Java / Python / R | Java / Scala |
我的经验:如果你对延迟要求是秒级以内,Flink 和 Kafka Streams 都能满足。但一旦涉及复杂的状态计算(比如 session window、多流 join),Flink 的优势就体现出来了。我在做用户实时画像时,Flink 的状态 TTL 和 checkpoint 机制帮了大忙。
2.3 场景适配:什么场景选什么引擎
光看对比表还不够,得落到具体场景里。我按常见的实时数据产品场景,给你拆解一下:
场景一:实时数仓 / ETL
这是 Flink 的强项。流批一体、SQL 支持完善、CDC 接入方便。我去年帮一家电商公司搭实时数仓,Flink + Kafka + Hudi 的组合,从 MySQL binlog 到 OLAP 查询,延迟控制在 30 秒以内。
- 推荐:Flink(首选)
- 备选:Spark Streaming(如果已有 Spark 生态)
- 不推荐:Kafka Streams(状态管理能力有限)
场景二:实时风控 / 反欺诈
延迟要求极高,通常需要毫秒级响应。而且规则复杂,需要 CEP(复杂事件处理)。
- 推荐:Flink(CEP 库 + 低延迟)
- 备选:Kafka Streams(简单规则可用)
- 不推荐:Spark Streaming(微批模型延迟太高)
我曾经踩过的坑:在一家金融公司做实时风控,初期选了 Spark Streaming,结果微批模型导致规则触发延迟了 5 秒,被业务方投诉。后来换成 Flink,延迟降到 200ms 以内。所以,风控场景千万别省这个选型时间。
场景三:实时监控 / 告警
这类场景通常逻辑简单,但数据量大。Kafka Streams 的轻量级优势就体现出来了。
- 推荐:Kafka Streams(部署简单、延迟低)
- 备选:Flink(如果后续需要复杂分析)
- 不推荐:Spark Streaming(太重了)
场景四:实时机器学习特征工程
需要高吞吐、低延迟的特征计算,同时要支持模型在线服务。
- 推荐:Flink(状态管理 + 特征回溯)
- 备选:Spark Streaming(批流统一训练)
- 不推荐:Kafka Streams(状态规模受限)
2.4 选型决策矩阵
我整理了一个决策矩阵,你可以直接拿来用。把业务需求往里面一套,答案就出来了。
| 决策条件 | Flink | Spark Streaming | Kafka Streams |
|---|---|---|---|
| 延迟要求 < 100ms | ✅ | ❌ | ✅ |
| 延迟要求 1-10s | ✅ | ✅ | ✅ |
| 需要精确一次语义 | ✅ 原生支持 | ⚠️ 需外部事务 | ❌ 至少一次 |
| 复杂状态计算(Join/Window) | ✅ 强 | ⚠️ 一般 | ⚠️ 有限 |
| 已有 Spark 技术栈 | ⚠️ 可共存 | ✅ 无缝 | ❌ 不相关 |
| 团队 Java 为主 | ✅ | ⚠️ Scala 更优 | ✅ |
| 运维能力弱 | ⚠️ 需集群 | ⚠️ 需集群 | ✅ 无集群 |
| 数据源仅 Kafka | ✅ | ✅ | ✅ 最佳 |
选型口诀:复杂状态选 Flink,批流一体选 Spark,轻量简单选 Kafka Streams。别贪多,够用就好。
2.5 我的选型流程
最后分享一套我自己的选型流程。每次做实时项目,我都会按这个步骤走一遍:
- 明确延迟要求:先问业务方,你能接受几秒的延迟?如果答案是"越快越好",那就得按毫秒级来设计。
- 评估状态复杂度:需要做 session window 吗?需要多流 join 吗?状态规模会超过 100GB 吗?
- 盘点团队能力:团队擅长 Java 还是 Scala?有没有 Flink/Spark 的运维经验?
- 考虑生态兼容:现有的数据基础设施是什么?Kafka 版本?Hadoop 版本?
- 做 POC 验证:别光看文档,拿真实数据跑一遍。我见过太多"理论上可行"最后翻车的案例。
一个小建议:如果你还在犹豫,可以先从 Kafka Streams 起步。它部署成本最低,后期迁移到 Flink 也相对平滑。我有个项目就是这样,先用 Kafka Streams 快速验证业务,半年后流量涨了 10 倍,无缝迁移到了 Flink。