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

做实时特征工程,第一关不是写代码,而是选引擎。

选错了,后面三个月都在填坑。选对了,事半功倍。今天我就把这三个主流引擎的底牌翻出来,结合我踩过的坑,给你一份能直接用的选型指南。

核心观点:没有最好的引擎,只有最合适的场景。选型的关键在于你的数据规模、延迟要求、以及团队的技术栈积累。

2.1 三驾马车:各自的血统与定位

先看一张总览图,把三者的定位搞清楚。

实时计算引擎选型全景图 Apache Flink Spark Streaming Kafka Streams 核心特征 核心特征 核心特征 真正的事件驱动 精确一次语义 状态管理强大 微批次处理 与批处理统一 生态丰富 轻量级库 无独立集群 与Kafka深度绑定 适用场景对比 复杂事件处理 实时特征计算 状态密集型作业 准实时ETL 批流一体场景 已有Spark技术栈 简单流处理 Kafka原生生态 轻量级部署 选型建议:实时特征工程首选 Flink;已有 Spark 生态选 Spark Streaming;轻量级场景选 Kafka Streams 三者并非互斥,实际生产中常组合使用

2.2 Apache Flink:实时特征工程的王者

Flink 是我个人在实时特征工程中的首选。为什么?因为它天生就是为「事件驱动」而生的。

你想想看,特征工程的核心是什么?是状态。用户的点击序列、滑动窗口内的统计值、实时的行为标签——这些都是状态。Flink 的状态管理是我用过的引擎里最成熟的。

我的经验:在做一个用户实时画像系统时,我们需要维护每个用户最近30分钟的点击序列。Flink 的 KeyedState 配合 RocksDB 状态后端,轻松支撑了百万级用户的实时状态更新。换做其他引擎,光状态管理就能让你掉一层皮。

Flink 的核心优势

  • 真正的流处理:每条数据到达即处理,延迟在毫秒级。不是微批次,是真正的逐条处理。
  • 精确一次语义:端到端的 exactly-once,对于金融风控等场景至关重要。
  • 事件时间语义:支持乱序事件处理,watermark 机制成熟。我在处理 IoT 传感器数据时,设备上报时间经常乱序,Flink 的 watermark 帮我解决了大问题。
  • 丰富的 Connector:Kafka、Pulsar、HDFS、Redis、Elasticsearch……几乎你能想到的数据源都有现成的连接器。

Flink 的短板

  • 学习曲线陡峭:概念多(Checkpoint、Savepoint、State Backend、Slot……),新手容易懵。
  • 运维成本高:需要独立集群,JobManager 挂了要恢复,资源调优是个技术活。
  • 批处理能力弱于 Spark:虽然 Flink 也在推批流一体,但批处理场景还是 Spark 更成熟。

2.3 Spark Streaming:批流一体的老牌劲旅

Spark Streaming 的核心思想是「微批次」。把实时数据流切成一个个小批次,然后用 Spark 的批处理引擎去算。说白了,就是用批处理的方式模拟实时。

我记得在 2018 年,我接手了一个实时 ETL 项目。团队里全是 Spark 工程师,没人懂 Flink。当时我们硬着头皮用 Spark Streaming 做了实时特征计算。结果呢?延迟在 5-10 秒,勉强能用,但状态管理是真的痛苦。

避坑指南:我曾经在一个项目中,用 Spark Streaming 做滑动窗口统计。窗口大小 5 分钟,滑动步长 10 秒。结果每个窗口都要重新计算,状态膨胀得厉害,GC 频繁。后来改用 Flink 的滑动窗口,性能提升了 3 倍。所以,如果你的场景涉及大量状态操作,慎用 Spark Streaming。

Spark Streaming 的核心优势

  • 与 Spark 生态无缝集成:如果你已经在用 Spark 做批处理,Spark Streaming 的学习成本几乎为零。
  • 强大的 SQL 支持:Structured Streaming 让用户可以用 SQL 写流处理逻辑,门槛低。
  • 社区活跃:文档丰富,遇到问题容易找到解决方案。

Spark Streaming 的短板

  • 微批次架构的固有限制:延迟在秒级,无法做到毫秒级响应。
  • 状态管理较弱:虽然 Structured Streaming 改进了状态管理,但和 Flink 比还是有差距。
  • 资源消耗大:每个微批次都要调度资源,小批次场景下资源利用率不高。

2.4 Kafka Streams:轻量级的流处理库

Kafka Streams 不是框架,是一个 Java 库。它不需要独立的集群,直接嵌入你的应用里。你想想看,这意味着什么?部署简单,运维成本低。

我在做一个日志实时聚合的小项目时,就用过 Kafka Streams。需求很简单:统计每台机器的 QPS,输出到另一个 Topic。整个代码不到 100 行,打包成 jar 直接跑,连集群都不用搭。

适用场景:Kafka Streams 最适合「轻量级」的流处理任务。比如简单的过滤、转换、聚合。如果你的业务逻辑复杂,需要多流 Join、复杂窗口、外部状态查询,那还是上 Flink 吧。

Kafka Streams 的核心优势

  • 无独立集群:作为库嵌入应用,部署简单,运维成本低。
  • 与 Kafka 深度集成:利用 Kafka 的分区机制实现并行处理,天然支持 exactly-once。
  • 轻量级:适合微服务架构中的流处理需求。

Kafka Streams 的短板

  • 功能有限:复杂的状态操作、多流 Join、事件时间处理不如 Flink 强大。
  • 仅支持 Java:虽然也有 Kafka Streams DSL,但本质上还是 Java 生态。
  • 调试困难:作为库嵌入应用,出现问题难以隔离排查。

2.5 选型对比:一张表说清楚

对比维度 Apache Flink Spark Streaming Kafka Streams
架构模式 事件驱动(逐条处理) 微批次(Mini-Batch) 事件驱动(库模式)
延迟 毫秒级 秒级 毫秒级
状态管理 强大(KeyedState、OperatorState) 中等(StateStore) 基础(StateStore)
精确一次语义 端到端支持 支持(需配置) 支持(依赖Kafka)
事件时间 原生支持,Watermark成熟 支持(Structured Streaming) 支持(有限)
部署方式 独立集群 独立集群 嵌入应用(无集群)
学习曲线 陡峭 中等(有Spark基础) 平缓(Java开发者友好)
适用场景 复杂实时特征、状态密集型作业 准实时ETL、批流一体 轻量级流处理、Kafka原生生态

2.6 我的选型建议

说了这么多,到底怎么选?我给出三个原则:

  1. 看延迟要求:毫秒级响应选 Flink 或 Kafka Streams;秒级响应 Spark Streaming 也能接受。
  2. 看状态复杂度:复杂状态操作(多流 Join、长窗口、状态回溯)无脑选 Flink。
  3. 看团队技术栈:团队全是 Spark 工程师,且延迟要求不高,Spark Streaming 是务实之选。团队 Java 为主,任务简单,Kafka Streams 性价比最高。

我的最终建议:对于实时特征工程这个领域,我个人强烈推荐 Flink。特征工程天然就是「状态密集型」的,Flink 的状态管理、事件时间语义、精确一次保证,几乎是为这个场景量身定做的。如果你正在从零搭建实时特征平台,别犹豫,选 Flink。

当然,实际生产中三者并不互斥。我见过很多团队用 Flink 做核心特征计算,用 Kafka Streams 做简单的数据预处理,用 Spark Streaming 做离线批处理的补充。工具是死的,人是活的。理解了各自的优劣,你就能在合适的场景用合适的工具。