4、流批一体架构原理:Lambda架构与Kappa架构、流处理(Flink/Spark Streaming)、批处理(Spark/MapReduce)、流批融合的挑战

聊到流批一体,绕不开两个经典架构:Lambda 和 Kappa。我刚开始接触大数据时,Lambda 还是主流。那时候大家觉得,批处理准,流处理快,那就两条腿走路呗。后来发现,两条腿走路是挺稳,但维护成本也翻倍了。

4.1 Lambda 架构:两条腿走路

Lambda 架构的核心思路很简单:

  • 批处理层:用 Spark、MapReduce 跑全量数据,保证准确性。
  • 流处理层:用 Flink、Storm 处理实时数据,保证低延迟。
  • 服务层:合并两边的结果,对外提供服务。

听起来很完美对吧?但实际落地时,坑不少。

我曾经踩过的坑: 在某个金融风控项目中,批处理层和流处理层各自维护一套逻辑。结果某次规则变更,只改了流处理层,批处理层忘了同步。线上跑了两周才发现数据对不上。嗯,从那以后,我要求两套代码必须走同一个代码仓库,用同一个规则引擎。

Lambda 架构的优缺点,我整理了一张表:

维度 说明
优点 批处理保证最终一致性,流处理保证实时性,各司其职
缺点 两套代码、两套运维、两套存储,维护成本高
适用场景 对实时性和准确性都有强要求的场景,比如金融交易、实时风控

4.2 Kappa 架构:一条路走到黑

Kappa 架构是 Lambda 的简化版。它只保留流处理层,批处理被看作「特殊的流处理」——把历史数据重新回放一遍就行。

说白了,Kappa 的核心思想是:一切皆流。你想想看,如果流处理引擎足够强,能处理无限数据流,那为什么还要单独搞一套批处理?

我个人习惯: 在向量数据处理场景中,Kappa 架构更友好。因为向量数据的更新频率高,而且需要实时构建索引。用 Kappa 架构,所有数据都走流处理,索引也能实时更新,省去了批处理层和流处理层数据对齐的麻烦。

但 Kappa 架构也有自己的问题:

  • 历史数据重放:如果数据量太大,重放一次可能要好几个小时。
  • Exactly-Once 语义:流处理要做到精确一次,对引擎要求很高。
  • 状态管理:流处理的状态会越来越大,需要合理管理。

4.3 流处理引擎:Flink vs Spark Streaming

说到流处理,现在主流就是 Flink 和 Spark Streaming。我两个都用过,说说我的感受。

Flink:真正的流处理

Flink 是真正的流处理引擎。每条数据来了,立刻处理。它的核心是:

  • 事件驱动:每条数据都是一个事件,触发计算。
  • 状态管理:内置状态后端,支持大规模状态存储。
  • Exactly-Once:通过 Checkpoint 机制保证精确一次。

我在项目中用 Flink 处理过向量数据的实时索引更新。每条向量数据进来,Flink 立刻计算它的向量值,然后更新到索引中。延迟控制在毫秒级。

Spark Streaming:微批处理

Spark Streaming 本质上是微批处理。它把数据流切成一个个小批次,每个批次用 Spark 的批处理引擎来跑。

  • 微批次:默认批次间隔 100ms,延迟比 Flink 高一些。
  • 生态丰富:Spark 的 MLlib、GraphX 都能直接用。
  • 容错机制:基于 RDD 的血统,容错成本较高。
避坑指南: 如果你的场景对延迟要求不高(比如秒级),Spark Streaming 完全够用。但如果你需要毫秒级响应,比如实时推荐、在线广告,那 Flink 是更好的选择。我曾经在一个广告点击率预估项目中,用 Spark Streaming 跑,延迟一直在 500ms 左右,换成 Flink 后降到了 50ms。

4.4 批处理引擎:Spark vs MapReduce

批处理这块,现在基本是 Spark 的天下。MapReduce 虽然还在用,但已经很少作为主力了。

维度 Spark MapReduce
计算模型 DAG(有向无环图) Map + Reduce 两阶段
中间结果 内存存储,速度快 磁盘存储,速度慢
易用性 API 丰富,支持 SQL、ML 代码量大,调试困难
适用场景 迭代计算、交互式查询 超大规模数据、稳定性要求高

在向量数据处理中,批处理主要用于:

  • 全量索引构建:每天凌晨跑一次,构建全量向量索引。
  • 历史数据重算:当算法模型更新时,重新计算历史数据的向量值。
  • 数据清洗:对原始数据进行去重、归一化等预处理。

4.5 流批融合的挑战

流批一体听起来很美,但真正做起来,挑战不少。我总结了几个核心难点:

  1. 语义一致性:流处理和批处理对「时间」的理解不同。流处理用事件时间,批处理用处理时间。怎么对齐?
  2. 状态管理:流处理的状态是动态的,批处理的状态是静态的。怎么统一管理?
  3. 容错机制:流处理用 Checkpoint,批处理用重试。怎么保证 Exactly-Once?
  4. 存储统一:流处理的数据存在 Kafka,批处理的数据存在 HDFS。怎么打通?
我曾经踩过的坑: 在某个电商推荐项目中,我们用 Flink 做实时推荐,用 Spark 做离线训练。结果发现,实时推荐的结果和离线训练的结果对不上。查了半天,发现是时间窗口的语义不一致。Flink 用事件时间,Spark 用处理时间,差了 5 分钟。后来统一用事件时间,问题才解决。

下面这张图,是我对 Lambda 和 Kappa 架构的对比总结:

Lambda vs Kappa 架构对比 Lambda 架构 批处理层 (Spark/MapReduce) 流处理层 (Flink/Storm) 服务层 (合并结果) Kappa 架构 流处理层 (Flink) — 一切皆流 服务层 (直接输出) 核心区别: Lambda:批处理 + 流处理,两套代码,两套运维,保证准确性和实时性。 Kappa:只有流处理,历史数据通过重放实现,简化架构,降低维护成本。

4.6 流批融合的实践思路

说了这么多挑战,那到底怎么落地?我分享几个实践思路:

  • 统一数据源:所有数据先入 Kafka,流处理和批处理都从 Kafka 消费。这样数据源就统一了。
  • 统一计算引擎:尽量用同一个引擎,比如 Flink 既做流处理,也做批处理(Flink 的 Batch 模式)。
  • 统一存储:用对象存储(如 HDFS、S3)作为统一存储层,流处理和批处理都读写同一份数据。
  • 统一元数据:用 Hive Metastore 或类似工具,统一管理表结构、分区信息。
我个人习惯: 在向量数据处理中,我倾向于用 Flink 做流处理,用 Spark 做批处理。Flink 负责实时索引更新,Spark 负责全量索引构建和模型训练。两套引擎通过 Kafka 和 HDFS 打通,数据流清晰,维护成本可控。

流批一体不是银弹,但它确实能解决很多实际问题。关键在于,你要清楚自己的场景,选择合适的架构,而不是盲目追求「一体」。嗯,这一章的内容就到这里,希望对你有帮助。