2. 批处理与流处理基础
在构建批流一体图谱API之前,必须深刻理解批处理与流处理的核心原理、主流引擎的架构差异,以及两种架构模式的演进路径。本章将系统梳理MapReduce/Spark的批处理原理、Flink/Storm的流处理原理,并对比Lambda与Kappa两种经典架构。
2.1 批处理原理:MapReduce 与 Spark
批处理(Batch Processing)的核心特征是对有界、静态的数据集进行一次性全量计算,强调高吞吐、高延迟(秒级到小时级)。
2.1.1 MapReduce 计算模型
MapReduce 是 Google 提出的经典批处理范式,分为两个阶段:
- Map 阶段:将输入数据切分为独立分片,每个分片由 Map 任务并行处理,输出键值对。
- Shuffle 阶段:对 Map 输出的键值对进行分区、排序、合并,将相同键的数据路由到同一个 Reduce 任务。
- Reduce 阶段:对每个键对应的值列表进行聚合计算,输出最终结果。
关键特征:数据落盘(HDFS)→ 计算移动(而非数据移动)→ 高容错(任务级重试)→ 磁盘I/O密集。
2.1.2 Spark 计算模型
Spark 在 MapReduce 基础上引入 RDD(弹性分布式数据集) 和 DAG(有向无环图) 执行引擎,将中间结果尽可能保留在内存中,避免频繁磁盘I/O。
| 对比维度 | MapReduce | Spark |
|---|---|---|
| 数据存储 | 中间结果强制落盘(HDFS) | 优先内存缓存,内存不足时溢写到磁盘 |
| 执行模型 | 固定两阶段(Map + Reduce) | DAG 多阶段(可包含多个宽依赖) |
| 延迟 | 分钟级(磁盘I/O瓶颈) | 秒级(内存计算) |
| 编程接口 | 仅 Java(原生) | Scala / Java / Python / SQL |
| 容错机制 | 任务级重试 + 数据副本 | RDD Lineage 血统重算 |
实战提示:在批流一体图谱API中,批处理层通常使用 Spark 进行全量历史数据重建(如全量实体关系图构建),利用其内存计算优势加速大规模图遍历与聚合。
2.2 流处理原理:Flink 与 Storm
流处理(Stream Processing)的核心特征是对无界、动态的数据流进行持续、低延迟计算,强调毫秒级延迟、事件时间语义、状态管理与精确一次语义。
2.2.1 Storm 流处理模型
Storm 是早期的分布式流处理框架,采用 Topology(拓扑) 描述计算逻辑:
- Spout:数据源,从外部系统读取数据流并发射元组(Tuple)。
- Bolt:处理节点,接收元组并执行过滤、聚合、连接等操作。
- Stream Grouping:定义元组在 Bolt 之间的分发策略(Shuffle、Fields、All 等)。
局限性:Storm 采用 at-least-once 语义(通过 ACK 机制),无法原生保证精确一次;状态管理依赖外部存储(如 Redis),延迟较高;不支持事件时间语义。
2.2.2 Flink 流处理模型
Flink 是新一代流处理引擎,核心设计理念是 流就是数据,批是流的特例:
- DataStream API:以数据流为中心,支持事件时间(Event Time)、处理时间(Processing Time)、摄入时间(Ingestion Time)。
- Checkpoint 机制:基于分布式快照(Chandy-Lamport 算法变种),实现精确一次(Exactly-Once)语义。
- 状态后端:支持 MemoryStateBackend、FsStateBackend、RocksDBStateBackend,管理算子状态。
- Watermark:用于处理乱序事件,触发窗口计算。
| 对比维度 | Storm | Flink |
|---|---|---|
| 处理语义 | At-least-once(ACK 机制) | Exactly-Once(Checkpoint + 两阶段提交) |
| 时间语义 | 仅处理时间 | 事件时间 / 处理时间 / 摄入时间 |
| 状态管理 | 依赖外部存储 | 内置状态后端(内存 / 文件 / RocksDB) |
| 窗口支持 | 有限窗口(需手动实现) | 滚动 / 滑动 / 会话窗口 + 自定义窗口 |
| 延迟 | 毫秒级(但状态访问慢) | 毫秒级(状态本地化) |
| 容错恢复 | 重放数据(可能重复) | 精确恢复(Checkpoint + 对齐) |
实战提示:在批流一体图谱API中,流处理层通常使用 Flink 处理实时增量数据(如实时实体关系变更、属性更新),利用其事件时间语义保证图谱数据的时间一致性。
2.3 Lambda 架构与 Kappa 架构对比
在批流一体系统设计中,架构选型直接决定数据一致性、开发复杂度和运维成本。两种主流架构模式如下:
2.3.1 Lambda 架构
Lambda 架构由 Nathan Marz 提出,将数据处理分为三层:
- 批处理层(Batch Layer):使用 MapReduce / Spark 对全量历史数据进行计算,生成不可变的批视图(Batch View)。
- 流处理层(Speed Layer):使用 Storm / Flink 对实时增量数据进行计算,生成近实时视图(Real-time View)。
- 服务层(Serving Layer):合并批视图与实时视图,对外提供统一查询接口。
优点:容错性强(批处理可重算)、历史数据完整、实时延迟低。
缺点:两套代码逻辑(批 + 流)、数据合并复杂、运维成本高。
缺点:两套代码逻辑(批 + 流)、数据合并复杂、运维成本高。
2.3.2 Kappa 架构
Kappa 架构由 Jay Kreps 提出,核心思想是只用一套流处理引擎处理所有数据:
- 所有数据(包括历史数据)都通过消息队列(如 Kafka)以流的形式输入。
- 流处理引擎(如 Flink)统一处理全量数据,支持数据重放(Replay)以修正错误。
- 无需独立的批处理层,简化架构。
优点:单一代码逻辑、架构简洁、易于维护。
缺点:对消息队列的存储和重放能力要求高、历史数据重放耗时较长。
缺点:对消息队列的存储和重放能力要求高、历史数据重放耗时较长。
| 对比维度 | Lambda 架构 | Kappa 架构 |
|---|---|---|
| 处理引擎 | 批处理 + 流处理(两套) | 仅流处理(一套) |
| 代码维护 | 两套代码(批逻辑 + 流逻辑) | 一套代码(流逻辑) |
| 数据一致性 | 最终一致(需合并批视图与实时视图) | 精确一次(流引擎保证) |
| 历史数据重算 | 批处理层直接重算 | 消息队列重放(依赖 Kafka 存储) |
| 延迟 | 批处理延迟高(分钟级),流处理延迟低 | 统一低延迟(毫秒级) |
| 适用场景 | 对历史数据完整性要求极高、实时与批处理逻辑差异大 | 实时性要求高、希望简化架构、消息队列存储充足 |
实战提示:在批流一体图谱API中,推荐采用 Kappa 架构 作为基础,使用 Flink 统一处理全量历史数据(通过 Kafka 重放)和实时增量数据。仅在需要大规模全量图重建(如 T+1 全量实体关系图)时,引入 Spark 批处理作为补充,形成“Kappa 为主、Lambda 为辅”的混合模式。
2.4 本章小结
批处理与流处理是批流一体系统的两大基石:
- 批处理:MapReduce 奠定基础,Spark 通过内存计算和 DAG 优化大幅提升性能,适合全量历史数据重建。
- 流处理:Storm 提供早期流处理能力,Flink 以事件时间、状态管理和精确一次语义成为现代流处理标准,适合实时增量数据处理。
- 架构选型:Lambda 架构成熟但复杂,Kappa 架构简洁但依赖消息队列能力。在批流一体图谱API中,推荐以 Kappa 架构为主,必要时引入 Spark 批处理作为补充。
下一阶段:在掌握批流处理基础后,我们将进入图谱数据模型设计,学习如何将实体、关系、属性映射为可被批流引擎高效处理的数据结构。