3. 技术选型与架构:Lambda、Kappa 与流批一体

聊到增量计算,绕不开一个核心问题:架构怎么选?

我见过不少团队,一上来就追新框架,结果业务跑不起来。说白了,选架构就是选妥协。你得在实时性、准确性、开发成本和运维复杂度之间找平衡。

这一节,我把三种主流架构掰开揉碎讲清楚。再附上我对 Flink、Spark Streaming、Kafka Streams 的真实体感。

3.1 Lambda 架构:经典但沉重

Lambda 架构是 2011 年由 Nathan Marz 提出的。它的核心思路很简单:用两条路处理数据。

  • 批处理层(Batch Layer):全量数据,高延迟,保证最终准确。
  • 流处理层(Speed Layer):实时数据,低延迟,提供近似结果。
  • 服务层(Serving Layer):合并两边的结果,对外提供服务。

我的经验:Lambda 架构最大的坑,不是技术实现,而是逻辑一致性。批处理和流处理用两套代码,同样的业务逻辑要写两遍。我曾经在一个金融项目中排查过三天,才发现批处理窗口和流处理窗口的聚合逻辑差了 5 分钟。那感觉,真是一言难尽。

注意:Lambda 架构的运维成本很高。你需要维护两套管道、两套存储、两套监控。除非你的团队足够大,否则我不建议中小团队直接上 Lambda。

3.2 Kappa 架构:简化,但有前提

Kappa 架构是 Jay Kreps 提出的。他当时觉得 Lambda 太复杂了,就问了一句:为什么不用一套流引擎搞定所有事?

Kappa 的核心思想:所有数据都走流处理。批处理只是流处理的一个特例——把历史数据重新回放一遍。

  • 统一入口:所有数据进入 Kafka 等消息队列。
  • 流处理引擎:实时处理新数据,也能回溯处理历史数据。
  • 结果存储:输出到数据库或文件系统。

嗯,这里要注意。Kappa 架构有个硬前提:你的消息队列必须能保存全量历史数据。Kafka 可以做到,但存储成本你得算清楚。我见过一个团队,Kafka 集群的磁盘撑了三个月就爆了,最后不得不回退到 Lambda。

避坑指南:我曾经在 IoT 场景中尝试过纯 Kappa。数据量每天 10TB,Kafka 保留 7 天就撑不住了。最后我们妥协了:热数据走 Kappa,冷数据走离线批处理。你看,架构从来不是非黑即白。

3.3 流批一体架构:理想与现实

流批一体,是近几年最火的概念。它的目标很性感:一套 API,一套引擎,同时支持流和批。

Flink 是这方面的代表。它认为「批是有界流,流是无界批」。你写一套代码,引擎自动决定怎么执行。

  • 统一 API:DataStream API 和 Table API 同时覆盖流和批。
  • 事件时间语义:不再依赖数据到达时间,而是数据本身携带的时间戳。
  • 精确一次语义:端到端的一致性保证。

说实话,流批一体在理论上是完美的。但在实际项目中,我遇到过不少问题。比如,批处理场景下的数据倾斜,在流模式下可能被放大。再比如,状态后端的管理,流和批的 checkpoint 策略完全不同。

我的建议:如果你的业务场景以实时为主,偶尔跑跑历史回溯,流批一体是很好的选择。但如果你的批处理任务很重(比如每天几百张 Hive 表),我建议还是保留专门的批处理引擎。

3.4 主流框架对比:Flink vs Spark Streaming vs Kafka Streams

选框架,我一般看三个维度:延迟、吞吐、生态。下面这张表是我个人的总结。

维度 Apache Flink Spark Streaming Kafka Streams
处理模型 真正的逐条流处理 微批次(Micro-batch) 流处理(基于 Kafka 分区)
延迟 亚秒级(毫秒) 秒级(通常 1-5 秒) 亚秒级(毫秒)
吞吐 高(依赖状态后端) 极高(批量处理优势) 中(受限于 Kafka 分区)
状态管理 内置状态后端(RocksDB/Heap) 依赖外部存储(Redis/HBase) 内置状态存储(RocksDB)
精确一次 原生支持 支持(需配置) 支持(需幂等生产者)
生态集成 丰富(Hive/HBase/ES/Kafka) 极丰富(Hadoop 全家桶) 仅限 Kafka 生态
学习曲线 中高 中 低
适用场景 实时 ETL、风控、监控 离线批处理、准实时报表 轻量级流处理、Kafka 原生应用

3.4.1 Flink:实时计算的王者

我个人最常用 Flink。它的优势在于真正的逐条处理和强大的状态管理。你想想看,在风控场景中,每一条数据都要在毫秒级内判断是否违规。Spark Streaming 的微批次模型,天然做不到这一点。

但 Flink 也有缺点。它的 checkpoint 机制在大状态场景下很吃资源。我曾经有一个任务,状态大小到了 100GB,每次 checkpoint 都要卡好几秒。后来我们优化了状态结构,才把问题解决。

3.4.2 Spark Streaming:批处理的延伸

Spark Streaming 本质上是把流切成一个个小批次。它的优势在于生态。如果你的团队已经用了 Spark 做离线计算,那么扩展到流处理是很自然的选择。

不过,微批次模型带来的延迟问题,在某些场景下是硬伤。我记得有个用户反馈,说他们的实时大屏数据总是慢 3 分钟。查到最后,发现是 Spark Streaming 的批次间隔设成了 2 分钟,再加上处理延迟,刚好 3 分钟。换成 Flink 后,延迟降到了 500 毫秒。

3.4.3 Kafka Streams:轻量级的选择

Kafka Streams 是一个库,不是框架。它直接嵌入你的应用里,不需要单独部署集群。对于轻量级流处理场景,比如数据过滤、字段转换、简单聚合,它非常合适。

但它的局限性也很明显。第一,只能处理 Kafka 里的数据。第二,状态管理能力有限。第三,没有统一的调度和监控。如果你要做复杂的多阶段 ETL,Kafka Streams 会显得力不从心。

我的选择逻辑:

  • 需要毫秒级延迟 + 复杂状态管理 → Flink
  • 已有 Spark 生态 + 秒级延迟可接受 → Spark Streaming
  • 轻量级任务 + 不想引入新框架 → Kafka Streams

3.5 架构选型决策树

说了这么多,到底怎么选?我画了一张图,帮你理清思路。

增量计算架构选型决策树 增量计算需求 实时性要求高? 数据量巨大? 团队规模小? Flink Spark Streaming Kafka Streams 选型建议 • 实时性高 + 状态复杂 → Flink(毫秒级延迟,内置状态管理) • 数据量大 + 已有 Spark 生态 → Spark Streaming(高吞吐,生态丰富) • 轻量级 + 不想引入新框架 → Kafka Streams(嵌入应用,零运维)

3.6 我的最终建议

架构选型没有银弹。Lambda 架构虽然重,但在某些需要严格数据一致性的场景下,它依然是最稳妥的选择。Kappa 架构很优雅,但前提是你搞定了 Kafka 的存储成本。流批一体是未来,但现阶段还有不少坑要填。

至于框架,我的建议是:别盲目追新。选你团队最熟悉的,选和你现有生态最匹配的。技术是为业务服务的,不是用来炫技的。

一句话总结:架构是骨架,框架是肌肉。骨架歪了,肌肉再强也跑不起来。先想清楚你要什么,再动手。