第2章:技术选型与架构设计

做实时数仓,第一步不是写代码,而是选型。我见过太多团队,上来就照着网上最火的组件搭一套,结果跑起来才发现——要么资源扛不住,要么延迟对不上业务要求。说白了,技术选型没有银弹,只有最适合你场景的组合。

这一章,我会把主流实时技术栈掰开揉碎讲清楚,再带你对比 Lambda 和 Kappa 两种架构的取舍。嗯,这些都是我踩过坑之后才真正理解的。

2.1 主流实时技术栈对比

实时数仓的核心链路,无非三块:采集传输、计算处理、存储查询。每块都有几个明星选手,我们一个一个看。

2.1.1 采集与传输层:Kafka

Kafka 在实时数仓里的地位,基本就是「数据总线」。所有源头数据——业务日志、埋点、CDC 变更——都先进 Kafka,再由下游消费。

我个人习惯把 Kafka 比作「实时数仓的主动脉」。为什么?因为它能扛住百万级 TPS 的写入,还能保证消息不丢、不重(只要你配置得当)。

核心优势:

  • 高吞吐、低延迟(毫秒级)
  • 数据持久化到磁盘,支持回溯消费
  • 分区机制天然支持并行处理

注意:Kafka 不是万能的。它不适合做复杂计算,也不适合存海量历史数据。我见过有人把 Kafka 当数据库用,结果 Topic 膨胀到几百个,运维直接崩溃。

2.1.2 计算处理层:Flink

Flink 是目前实时计算的事实标准。你想想看,它能做到「事件时间」语义下的精确一次处理,这在流计算里有多难?

我在项目中遇到过最典型的场景:用户点击流需要按 Session 分组,计算每个会话的停留时长。如果用 Spark Streaming,你得自己维护状态和 watermark,代码量翻倍。Flink 呢?一个 KeyedProcessFunction 加 Timer 就搞定了。

对比维度 Flink Spark Streaming Storm
处理模型 真正的流处理 微批次(准流) 流处理
延迟 毫秒级 秒级 毫秒级
状态管理 内置强状态 依赖外部存储 弱状态
精确一次 原生支持 需配置 至少一次
SQL 支持 成熟 较成熟 弱

说白了,如果你要做实时数仓的 ETL 和指标计算,Flink 是绕不开的选择。

2.1.3 存储查询层:ClickHouse vs Doris

这一层是争议最大的。ClickHouse 和 Doris 都是 OLAP 引擎,但设计哲学完全不同。

ClickHouse:列式存储,向量化执行,单表查询极快。我曾在 ClickHouse 上跑过百亿级数据的聚合查询,秒级出结果。但它有个硬伤——多表 Join 性能差,而且不支持事务。

Apache Doris:兼容 MySQL 协议,支持标准 SQL,Join 优化做得比 ClickHouse 好。它采用 MPP 架构,适合复杂分析场景。我在一个金融项目中用 Doris 替代了 ClickHouse,因为业务需要频繁的关联查询和实时更新。

我的建议:

  • 如果场景以单表聚合为主(比如用户行为分析),选 ClickHouse
  • 如果场景需要多表 Join、实时更新、或者团队熟悉 MySQL,选 Doris
  • 如果预算充足,两者可以共存——ClickHouse 做明细查询,Doris 做宽表分析

2.2 Lambda 架构与 Kappa 架构

聊完组件,我们看看架构层面的选择。实时数仓的架构演进,说白了就是 Lambda 和 Kappa 的博弈。

2.2.1 Lambda 架构:批流分离

Lambda 架构把数据处理分成两条路:

  • 批处理层:用 Spark/Hive 处理全量历史数据,保证数据准确性
  • 流处理层:用 Flink/Storm 处理实时增量数据,保证低延迟
  • 服务层:合并批和流的结果,对外提供服务

听起来很完美对吧?但我在实际项目中吃过它的苦头。维护两套代码、两套调度、两套运维,每次逻辑变更都要同步修改批和流,稍有不慎就对不上数。我记得有一次,批处理的结果和流处理的结果差了 0.5%,排查了整整两天,最后发现是窗口边界定义不一致。

避坑指南:Lambda 架构适合对数据准确性要求极高、且历史数据需要频繁重算的场景(比如金融对账)。但如果你的团队规模不大,我建议慎重——维护两套系统的成本,可能比数据延迟那几秒更致命。

2.2.2 Kappa 架构:批流一体

Kappa 架构的思路很直接:只用一套流处理引擎,搞定所有事情。历史数据通过「重新消费 Kafka 消息」来重算,不需要单独的批处理层。

你想想看,这多清爽?代码只有一套,运维只有一套,逻辑天然一致。Flink 的兴起让 Kappa 架构变得可行——它支持事件时间、状态后端、Checkpoint,理论上可以处理无限流数据。

但 Kappa 也不是没有代价。如果历史数据量巨大,重新消费 Kafka 消息可能需要几个小时。而且 Kafka 的消息保留时间有限(默认 7 天),超过这个时间的数据就重算不了了。

我的经验:

  • 如果数据源全部通过 Kafka 接入,且历史数据可以容忍「重新消费」的延迟,选 Kappa
  • 如果数据源包含离线文件(比如 HDFS 日志),或者需要频繁回溯几个月的数据,Lambda 更稳妥
  • 我个人更倾向 Kappa——它逼着你把数据管道做干净,而不是用批处理来「擦屁股」

2.3 架构对比与选型建议

为了让你看得更清楚,我画了一张对比图:

Lambda vs Kappa 架构对比 Lambda 架构 批处理层 (Spark) 流处理层 (Flink) 服务层:合并批+流结果 Kappa 架构 统一流处理层 (Flink) 服务层:直接输出结果 说明: Lambda 架构需要维护批和流两套代码,逻辑一致性和运维成本是主要痛点。 Kappa 架构只用一套流引擎,通过重新消费 Kafka 消息处理历史数据,更简洁但依赖消息保留时长。 Lambda 适用场景 • 历史数据需要频繁重算 • 数据准确性要求极高(如金融) • 数据源包含离线文件 Kappa 适用场景 • 数据全部通过 Kafka 接入 • 团队规模小,追求运维简洁 • 历史数据可容忍重算延迟

2.4 本章小结

技术选型没有标准答案,但有决策框架。我个人总结了三步:

  1. 先定架构:根据数据源和重算需求,选 Lambda 还是 Kappa
  2. 再选组件:Kafka 做总线,Flink 做计算,ClickHouse/Doris 做存储
  3. 最后验证:用真实数据压测,别信 Benchmark

我曾经在一个项目中,花了两周做技术选型,最后上线后还是发现 ClickHouse 的 Join 性能不满足需求,不得不切到 Doris。所以我的建议是——先跑一个最小原型,用真实数据验证,再决定。

一句话总结:实时数仓的架构选型,本质是在「准确性」和「简洁性」之间找平衡。没有完美的架构,只有适合你的架构。