第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 架构对比与选型建议
为了让你看得更清楚,我画了一张对比图:
2.4 本章小结
技术选型没有标准答案,但有决策框架。我个人总结了三步:
- 先定架构:根据数据源和重算需求,选 Lambda 还是 Kappa
- 再选组件:Kafka 做总线,Flink 做计算,ClickHouse/Doris 做存储
- 最后验证:用真实数据压测,别信 Benchmark
我曾经在一个项目中,花了两周做技术选型,最后上线后还是发现 ClickHouse 的 Join 性能不满足需求,不得不切到 Doris。所以我的建议是——先跑一个最小原型,用真实数据验证,再决定。
一句话总结:实时数仓的架构选型,本质是在「准确性」和「简洁性」之间找平衡。没有完美的架构,只有适合你的架构。