2、核心架构选型:Lambda vs Kappa,消息队列与流计算引擎

这一章,我们聊聊实时流水线的骨架选型。说白了,就是决定用什么姿势把数据从源头搬到下游。

我见过不少团队,一上来就追新框架,结果架构越搞越重,运维成本直接起飞。其实选型这事,没有银弹。你得想清楚:你的业务到底要什么?

2.1 架构模式:Lambda 与 Kappa 的抉择

先看两张经典的架构图。Lambda 架构,说白了就是「批流合一」——批处理层算全量,速度层算增量,最后合并。Kappa 架构呢?只留流处理一条线,历史数据重放就用流引擎重新跑一遍。

核心区别一句话:Lambda 用两条腿走路(批+流),Kappa 只用一条腿(纯流)。

我在 2018 年帮一家电商公司搭用户画像系统,当时选了 Lambda。为什么?因为他们的离线报表需要 T+1 的全量修正,而实时推荐又要求秒级响应。两条线各干各的,互不干扰。

但 Lambda 的坑也很明显——维护两套代码,两套集群。你想想看,批处理用 Hive/Spark SQL,流处理用 Flink,逻辑稍微不一致,数据就对不齐。我后来查过好几次凌晨的告警,都是因为批流合并时的时间窗口没对齐。

Kappa 架构就清爽多了。所有数据进 Kafka,Flink 从头消费,想重算历史?重置 offset 就行。但前提是:你的消息队列能存足够久的数据,且流引擎能扛住全量重放的压力。

对比维度 Lambda 架构 Kappa 架构
代码维护 两套(批+流) 一套(纯流)
历史修正 批处理层自动修正 需重放消息或重跑作业
资源消耗 较高(双集群) 较低(单集群)
适用场景 对数据一致性要求极高,有离线全量需求 纯实时场景,可接受短时回溯

避坑指南:我曾经见过一个团队,为了「技术潮流」硬上 Kappa,结果业务方要求每天凌晨跑一次全量对账,流引擎重放 3 天的数据要跑 6 小时。最后不得不加回批处理层,变成了「Lambda 披着 Kappa 的皮」。选型前,一定先问清楚业务对历史修正的容忍度。

2.2 消息队列选型:Kafka vs Pulsar

消息队列是实时流水线的「主动脉」。选错了,后面所有环节都跟着遭殃。

Kafka 不用多说,生态最成熟,国内大厂基本都在用。Pulsar 是后起之秀,主打存算分离和原生分层存储。

我个人的习惯是:如果团队规模不大(10 人以下),Kafka 是最稳妥的选择。文档多、踩坑经验多、招聘也容易。但如果你要支撑百万级 topic,或者需要跨地域复制,Pulsar 的架构优势就出来了。

特性 Apache Kafka Apache Pulsar
存储模型 分区日志(存算耦合) 存算分离(BookKeeper + Broker)
Topic 扩展性 分区数受限于磁盘和 IO 轻松支持百万级 topic
消息保留 基于日志段过期 原生分层存储(可保留无限久)
运维复杂度 中等(依赖 ZooKeeper) 较高(多组件协同)
数据重放 重置 offset 支持按时间、position 精确回溯

嗯,这里要注意一个细节:Kafka 的存储是跟 broker 绑定的。你扩容分区,往往需要重新均衡数据,这个过程对线上有影响。Pulsar 的存算分离,扩容 broker 几乎无感,存储层 BookKeeper 自动做负载均衡。

但 Pulsar 的客户端生态不如 Kafka 丰富。我去年做一个 IoT 项目,需要 MQTT 协议接入,Pulsar 原生支持,Kafka 还得搭桥接层。这种场景下,Pulsar 反而更省事。

我的建议:如果团队 Kafka 经验丰富,且 topic 数在几千以内,继续用 Kafka 没问题。如果从零搭建,且预期 topic 规模会快速增长,或者需要长时间保留消息(比如 Kappa 架构),Pulsar 值得一试。

2.3 流计算引擎选型:Flink vs Spark Streaming

流计算引擎是实时流水线的「大脑」。选型时,我主要看三点:实时性、状态管理、生态兼容。

Flink 是真正的逐条处理,事件时间语义原生支持。Spark Streaming 本质上是微批次,虽然 Spark 3.0 之后引入了结构化流,但底层还是微批次那一套。

为什么会这样?因为 Spark 的设计哲学是「批处理扩展出流」,而 Flink 是「流处理扩展出批」。出发点不同,导致行为差异。

我在一个金融风控项目里做过对比:同样的去重逻辑,Flink 的端到端延迟在 200ms 以内,Spark Streaming 在 2-5 秒。对于风控来说,5 秒的延迟意味着交易已经完成了,拦截就失去了意义。

对比维度 Apache Flink Spark Streaming
处理模型 逐条处理(真流) 微批次(伪流)
延迟 毫秒级 秒级
状态管理 原生强状态(ValueState, MapState) 依赖外部存储或 updateStateByKey
事件时间 原生支持,watermark 机制成熟 支持但精度受批次间隔影响
SQL 支持 Flink SQL 持续演进 Spark SQL 生态更成熟
与批处理统一 流批一体(同一 API) 流批分离(不同 API)

但 Spark Streaming 也有它的优势。如果你的团队已经重度使用 Spark 做离线,且实时性要求不高(比如分钟级报表),那 Spark Streaming 可以复用已有的 ETL 逻辑和运维体系,学习成本低很多。

一句话总结:要毫秒级延迟、复杂事件处理、强状态管理 → 选 Flink。要秒级延迟、与现有 Spark 生态集成、团队 Spark 经验丰富 → 选 Spark Streaming。

2.4 架构选型全景图

下面这张图,是我自己总结的选型决策流程。每次做新项目,我都会拿出来过一遍。

实时流水线核心架构选型全景图 业务需求分析 架构模式:Lambda vs Kappa 消息队列:Kafka vs Pulsar 流计算引擎:Flink vs Spark Streaming 技术选型决策输出 决策顺序:先定架构模式 → 再选消息队列 → 最后选流计算引擎,每一步都受上一步约束

你看,整个决策链条是自上而下的。先确定业务对实时性的要求,再选架构模式,然后消息队列和计算引擎要匹配。比如你选了 Kappa 架构,那消息队列最好支持长时间数据保留(Pulsar 或 Kafka 调大保留时间),流引擎要能稳定重放(Flink 的 checkpoint 机制更可靠)。

个人经验:我一般会先画一个这样的决策树,跟业务方和开发团队一起过一遍。很多时候,讨论过程中就能发现隐藏的坑。比如业务说「要实时」,但追问下去,其实 5 秒延迟也能接受。这时候 Spark Streaming 就够用了,没必要上 Flink 增加复杂度。