2. 实时计算引擎选型对比:Flink vs Spark Streaming vs Kafka Streams

做实时特征任务,选哪个引擎?

这个问题我几乎每次跟团队讨论架构时都会被问到。说实话,没有银弹。Flink、Spark Streaming、Kafka Streams 各有各的脾气。我这些年三个引擎都用过,踩过坑也填过坑。今天咱们就掰开揉碎聊聊,不同场景下它们的成本模型到底差在哪。

2.1 三驾马车:核心差异速览

先给个全景图。这三个引擎的定位其实不太一样:

  • Flink:真正的流式计算引擎。事件驱动,状态管理强,精确一次语义是原生能力。
  • Spark Streaming:本质是微批次。把流切成小批,用 Spark 的批处理引擎跑。延迟在秒级。
  • Kafka Streams:轻量级库,不是框架。嵌入你的应用里,依赖 Kafka 做状态和容错。

我习惯用一个比喻:Flink 像专业赛车手,为赛道而生;Spark Streaming 像 SUV,能越野也能跑高速;Kafka Streams 像自行车,灵活轻便,但别指望它拉重货。

选型核心原则:别只看性能指标。要看你的团队熟悉什么、你的基础设施是什么、你的特征任务对延迟和状态的敏感度有多高。

2.2 成本模型拆解:不止是机器钱

说到成本,很多人第一反应是“哪个引擎省机器”。其实成本模型要算四笔账:

成本维度 Flink Spark Streaming Kafka Streams
计算资源 中等偏高。状态后端 + checkpoint 吃内存和磁盘 高。微批次调度 + shuffle 吃 CPU 和网络 低。嵌入应用,无额外调度开销
存储资源 依赖状态后端(RocksDB 或 Heap),需要本地磁盘 依赖 HDFS/S3 做 checkpoint,存储成本高 依赖 Kafka 内部 topic,存储成本可控
运维成本 高。需要 Flink 集群 + JobManager HA 高。需要 YARN/K8s + Spark 集群 低。无独立集群,随应用部署
开发成本 中等。API 丰富但学习曲线陡 中等。Spark SQL 生态好,但微批次思维要转 低。纯 Java 库,API 简洁

你看,Flink 和 Spark Streaming 的运维成本都不低。我曾经在一个项目里,Flink 集群挂了,排查了半天发现是 JobManager 的堆内存配置不合理。嗯,这种坑只有自己踩过才知道疼。

2.3 场景一:高吞吐、低延迟、强状态

这是 Flink 的主场。

比如实时特征计算中的滑动窗口聚合、CEP 模式匹配、多流 join。这些任务对状态一致性要求极高,Flink 的精确一次语义和分布式快照机制是天然优势。

成本模型上,Flink 的瓶颈通常在状态后端。我建议:

  • 状态量小于 10GB:用 Heap StateBackend,性能最好
  • 状态量 10GB~100GB:用 RocksDB,但注意调优内存和磁盘 I/O
  • 状态量超过 100GB:考虑拆分任务或改用其他方案

我的经验:Flink 的 checkpoint 间隔别设太短。默认 500ms 太激进,我一般设 3~5 秒。太频繁的 checkpoint 反而会拖慢吞吐,得不偿失。

2.4 场景二:批流一体、已有 Spark 生态

如果你的团队已经重度使用 Spark,做 ETL、离线训练、报表分析,那 Spark Streaming 是自然选择。

成本优势在于复用。同一套集群、同一套运维体系、同一套代码规范。你想想看,不用再单独维护一套 Flink 集群,运维成本直接砍半。

但要注意,Spark Streaming 的微批次架构决定了它的延迟下限。我见过有人非要用 Spark Streaming 做毫秒级特征计算,结果折腾半天还是放弃了。说白了,工具选错了场景,再优化也白搭。

避坑指南:Spark Streaming 的背压机制在 2.x 版本里不够智能。我曾经遇到数据洪峰时,batch 堆积导致 OOM。后来升级到 3.x 并开启了 Dynamic Allocation 才缓解。如果你还在用 2.x,建议尽早升级。

2.5 场景三:轻量级、低运维、Kafka 原生

Kafka Streams 是我个人比较喜欢的一个选择,尤其是做简单的特征转换、过滤、富化这类任务。

它的成本模型很清晰:

  • 没有独立集群,随应用部署在容器或物理机上
  • 状态存储在 Kafka 的 changelog topic 里,天然持久化
  • 弹性伸缩靠调整分区数,不需要额外调度器

我有个项目,用 Kafka Streams 做实时用户画像特征计算。每天处理几十亿条事件,只用了 8 台 8C16G 的机器。换成 Flink 至少需要 12 台,而且还要搭集群。这就是轻量级的优势。

但 Kafka Streams 也有短板:

  • 不支持精确一次语义(只能做到至少一次)
  • 状态查询不方便,没有 Flink 的 Queryable State
  • 复杂窗口操作实现起来比较费劲

2.6 选型决策树:一张图说清楚

下面这张图是我自己总结的选型逻辑,帮你快速定位:

实时计算引擎选型决策树 实时特征任务 延迟要求 < 100ms ? 是 → 低延迟场景 否 → 秒级延迟可接受 状态量大 / 复杂窗口 ? Flink Kafka Streams 已有 Spark 生态 ? Spark Streaming Flink 说明 • 低延迟 + 强状态 → Flink 是首选 • 低延迟 + 轻量级 → Kafka Streams 更经济 • 秒级延迟 + 已有 Spark → Spark Streaming 复用成本最低

2.7 成本对比实战:一个特征任务的账单

拿一个真实的特征任务举例:实时计算用户过去 1 小时的点击率,数据量 10 万 QPS,状态量约 50GB。

我分别用三个引擎做过方案评估,结果如下:

项目 Flink Spark Streaming Kafka Streams
机器数量 12 台 8C16G 16 台 8C16G 8 台 8C16G(嵌入应用)
月机器成本 约 1.2 万 约 1.6 万 约 0.8 万
运维人力 0.5 人月 0.5 人月 0.1 人月
开发周期 2 周 3 周 1 周
延迟 P99 80ms 2.5s 120ms

你看,Kafka Streams 在机器成本和运维成本上优势明显,但延迟比 Flink 略高。Spark Streaming 最贵,延迟也最高,但如果你团队 Spark 能力强,开发成本可以忽略。

我的建议:别只看机器成本。运维人力和开发周期也是真金白银。我见过一个团队为了省机器钱选了 Kafka Streams,结果状态管理搞不定,最后又重写成 Flink,反而多花了两倍时间。

2.8 总结:选型没有标准答案

说了这么多,其实就一句话:场景决定选型,选型决定成本。

我个人习惯的做法是:

  • 新项目、低延迟、强状态 → Flink
  • 已有 Spark 生态、秒级延迟可接受 → Spark Streaming
  • 轻量级特征转换、低运维、Kafka 原生 → Kafka Streams

嗯,最后提醒一句:别迷信某个引擎。工具是死的,业务是活的。选型前先想清楚你的特征任务到底要什么,再动手。