1. 数仓架构演进:从传统数仓到Lambda架构,再到Kappa架构的演变历程与核心痛点

聊数仓架构演进,其实就是在聊一个核心问题:数据到底要等多长时间才能用?

我入行那会儿,跑一个离线ETL任务,凌晨两点调度,早上九点出报表,业务方已经觉得很满意了。后来业务越来越卷,老板早上九点要看昨天的数据?不行,得看实时的。于是架构就开始变了。

这一章,咱们就捋一捋这条演进路线——从传统数仓到Lambda,再到Kappa,看看每一步到底解决了什么问题,又留下了什么坑。

1.1 传统数仓:T+1的“慢工出细活”

传统数仓的核心模式,说白了就是T+1。今天的数据,明天才能用。

架构上通常长这样:

  • ODS层:原始数据落地,不做任何加工
  • DWD层:数据清洗、去重、标准化
  • DWS层:轻度汇总,按主题组织
  • ADS层:面向业务应用的数据集市

数据流是单向的、批量的。每天晚上跑一堆Sqoop、Spark或Hive任务,把业务库的数据拉过来,一层一层往下刷。

核心特征:

  • 数据延迟:24小时起步
  • 计算模式:批量调度
  • 存储介质:HDFS为主
  • 一致性:强,因为都是全量或增量快照

我在项目中遇到过一件事:业务方早上八点冲进来说“昨天的转化率不对,能不能重跑一下?”我说行,改个参数重新调度,中午之前能出来。他叹了口气说“中午出来,老板已经开完晨会了。”——这就是T+1的痛。

个人习惯:传统数仓适合财务对账、月度报表这类“晚一天没关系”的场景。但千万别用它做实时风控或大屏监控,会出事的。

1.2 Lambda架构:批流“两条腿走路”

为了解决延迟问题,Nathan Marz在2011年提出了Lambda架构。它的思路很直接:批处理保证全量准确,流处理保证低延迟。

架构上分三层:

层级 职责 技术选型(典型) 延迟
Batch Layer 全量数据计算,生成不可变的Master Dataset Hadoop/Spark 小时级
Speed Layer 实时增量计算,补偿Batch Layer的延迟 Storm/Flink 秒级
Serving Layer 合并Batch和Speed的结果,对外提供服务 HBase/Redis 准实时

听起来很完美对吧?但实际落地的时候,坑比想象的多。

我曾经踩过的坑:

  • 两套代码,两套逻辑:批处理用Spark SQL写一套,流处理用Flink SQL再写一套。业务逻辑稍微复杂点,两边对不齐,结果不一样。排查起来,批说流算错了,流说批算错了,最后发现是窗口边界定义不一致。
  • 数据合并的“最后一公里”:Serving Layer要同时读批和流的结果,然后做merge。如果批处理还没跑完,流数据已经更新了好几轮,合并逻辑写起来非常痛苦。
  • 运维成本翻倍:两套集群、两套监控、两套告警。出问题的时候,你得同时懂批和流,不然根本定位不了。

我记得有一次做实时大屏,Speed Layer用Flink算PV/UV,Batch Layer用Spark算历史对比。上线第二天,大屏上的“今日累计”和“昨日同期”对不上,差了3%。排查了两天,最后发现是批处理那边的去重逻辑用了Bloom Filter,流处理这边用了HyperLogLog——两个近似算法,精度不一样。你说这找谁说理去?

1.3 Kappa架构:流处理“一统天下”

Lambda架构的痛点太明显了。Jay Kreps在2014年提出了Kappa架构,核心思想就一句话:为什么不能只用一套流引擎搞定所有事?

Kappa架构的思路是:

  • 所有数据都当作流来处理
  • 历史数据重算,通过重新消费Kafka中的日志来实现
  • 不再区分Batch和Speed,只有一套Streaming Job

架构简化成两层:

  1. 消息队列层:Kafka,作为数据的“单一事实来源”
  2. 流处理层:Flink/Kafka Streams,负责所有计算逻辑

需要重算历史数据时,只需要把Kafka的offset重置到最早位置,重新跑一遍流任务就行。

Kappa架构的优势:

  • 一套代码,一套逻辑,不存在批流不一致的问题
  • 运维简单,只需要维护流处理集群
  • 数据延迟可控,全链路秒级

但别急着欢呼,Kappa也不是银弹。我在实际项目中遇到过几个棘手的问题:

Kappa架构的“暗面”:

  • 状态管理复杂:流处理是有状态的。如果任务挂了,重启后状态恢复是个大问题。Flink的Checkpoint/Savepoint机制虽然能解决,但配置不好容易OOM。
  • 历史数据重算效率低:Kafka里存了几个月的日志,要重算一遍,得从头消费到尾。数据量大的时候,重算一次可能要跑好几天。
  • Kafka存储成本高:为了支持重算,Kafka的日志保留时间得设得很长。TB级的数据存几个月,磁盘成本不是开玩笑的。
  • 批处理场景不友好:有些场景天然适合批处理,比如复杂的多表Join、全量数据扫描。硬要用流处理来实现,代码写起来很别扭,性能也不一定好。

说白了,Kappa架构更适合数据链路简单、状态不大、重算频率低的场景。如果你要处理几百张表的复杂ETL,还是老老实实用Lambda或者混合架构吧。

1.4 三种架构的对比与选型建议

我整理了一张对比表,方便你快速决策:

维度 传统数仓 Lambda架构 Kappa架构
数据延迟 T+1 秒级+小时级 秒级
开发成本 低 高(两套代码) 中
运维成本 低 高 中
数据一致性 强 最终一致(需合并) 最终一致
历史重算 容易 复杂 中等(依赖Kafka)
适用场景 报表、财务对账 实时大屏+离线报表 实时数仓、监控

我的选型建议:

  • 如果业务对实时性要求不高,传统数仓依然是最稳的选择
  • 如果既要实时又要离线,Lambda架构是“标准答案”,但要做好两套代码对齐的规范
  • 如果数据链路简单、团队规模小,Kappa架构能大幅降低运维成本
  • 如果预算充足、团队能力强,可以考虑“Lambda+Kappa”混合架构——核心链路用Kappa,复杂ETL用Lambda

1.5 架构演进的核心逻辑(SVG图)

下面这张图,把三种架构的演进关系和核心痛点串起来了。你一看就明白:

数仓架构演进核心逻辑 传统数仓 T+1 批量计算 ODS→DWD→DWS→ADS 痛点:延迟高 无法支持实时业务 Lambda架构 Batch Layer + Speed Layer 批流两条腿走路 痛点:两套代码 逻辑对齐难、运维成本高 Kappa架构 纯流处理 Kafka + Flink 一统天下 痛点:状态管理复杂 历史重算效率低 核心演进逻辑 从“慢但简单” → “快但复杂” → “又快又简单(但有新坑)” 本质是在延迟、成本、一致性之间不断做权衡 选型建议 传统数仓:稳 | Lambda:全 | Kappa:快 没有银弹,只有最适合你业务场景的架构

嗯,看到这里你应该明白了。架构演进不是“新的一定比旧的好”,而是业务需求倒逼技术升级。传统数仓稳,但慢;Lambda全,但重;Kappa快,但有新坑。

我个人习惯是:先搞清楚业务到底要什么,再选架构。别为了追新而追新,也别因为怕麻烦而固步自封。后面几章,咱们会深入聊Lambda和Kappa的具体实现细节,包括Flink SQL怎么写、Kafka怎么配、状态怎么管理——到时候你就知道,这些坑其实都有办法填。