一、数据湖的起源与演进:从数据仓库到数据湖,再到湖仓一体

聊增量计算之前,咱们得先搞清楚一个问题——数据湖到底是怎么来的?

我入行那会儿,正是数据仓库如日中天的年代。那时候大家做报表、跑BI,全靠ETL把数据洗得干干净净,再塞进星型模型里。听起来挺完美,对吧?但干过的人都知道,这玩意儿有个硬伤:数据进来之前,你就得把Schema定好。业务一变,模型就得跟着改,改一次折腾半个月。

1.1 数据仓库的黄金时代与隐痛

数据仓库的核心思想是「Schema on Write」——写入时定义结构。好处是查询快,坏处是灵活差。

典型数据仓库架构的特征:

  • 强Schema约束,写入前必须建模
  • 以SQL为核心,面向结构化数据
  • 存储成本高,扩展性有限
  • ETL流程复杂,变更代价大

我记得2014年在一个金融客户那里做项目,他们的数据仓库里光一个客户维度表就改了17次结构。每次改完,下游的ETL作业全得重跑,运维同学都快疯了。说白了,传统数仓适合「已知的已知」,但面对「未知的未知」就力不从心了。

1.2 数据湖的诞生:反其道而行之

2010年左右,Hadoop生态开始成熟。大家发现,与其先建模再存数据,不如先把原始数据扔进去,需要的时候再解析。这就是「Schema on Read」——读取时定义结构。

数据湖的核心承诺很简单:存得住、算得动、随便来。结构化、半结构化、非结构化数据,一股脑往里塞。我2016年帮一家电商公司搭数据湖时,他们每天要接入200+种日志格式,要是用传统数仓,光建模就得干半年。数据湖模式下,先存再说,后面慢慢梳理。

数据湖 vs 数据仓库 核心差异:

维度 数据仓库 数据湖
Schema策略 写入时定义(Schema on Write) 读取时定义(Schema on Read)
数据类型 结构化为主 结构化+半结构化+非结构化
存储成本 较高(需要预处理) 较低(原始存储)
数据质量 高(ETL清洗后) 低到中(原始数据)
变更灵活性 低 高

1.3 数据湖的「沼泽化」困境

理想很丰满,现实很骨感。数据湖很快暴露了问题——没有治理的数据湖,最后都会变成数据沼泽。

我见过太多案例了。数据往里堆,没人管格式、没人管质量、没人管生命周期。结果呢?想用数据的时候,发现根本不知道哪些数据是干净的,哪些是垃圾。更麻烦的是,数据湖不支持ACID事务,你写一半任务挂了,数据可能就残了。

为什么会这样?因为数据湖的底层存储(比如HDFS、S3)本身不支持文件级的事务和一致性语义。你跑一个批处理任务,写到一半失败了,留下的半成品文件没人清理。下次读数据的人,可能读到的是残缺的数据集。

我曾经踩过的坑:有一次在数据湖上跑一个全量重刷任务,跑了6个小时后集群OOM了。结果发现目标表里混着新旧两版数据,下游报表直接对不上数。从那以后,我坚持所有数据湖写入操作必须带「原子性标记」——要么全成功,要么全回滚。

1.4 湖仓一体:取长补短的进化

既然数据仓库太死板,数据湖太混乱,那能不能把两者的优点结合起来?这就是湖仓一体(Lakehouse)的出发点。

湖仓一体的核心思路是:用数据湖做存储底座,把数据仓库的事务、索引、SQL能力搬上来。像Delta Lake、Apache Iceberg、Apache Hudi这些技术,本质上就是在数据湖上加了事务层和元数据层。

我2019年开始接触Delta Lake,第一次看到它支持ACID事务时,说实话挺震撼的。你想想看,在S3上做事务,这以前谁敢想?

-- Delta Lake 示例:事务性写入
INSERT INTO events
SELECT * FROM raw_events
WHERE dt = '2024-01-15'
-- 如果失败,自动回滚,不会留下脏数据

湖仓一体带来的关键能力包括:

  • ACID事务:并发读写不冲突,失败自动回滚
  • Schema演进:支持字段增删改,不影响历史数据
  • 时间旅行:可以查询任意历史版本的数据
  • 统一存储:一份数据,同时支持BI分析和机器学习

1.5 为什么增量计算成了刚需?

好,前面铺垫了这么多,终于到核心问题了——为什么增量计算在湖仓一体时代成了刚需?

原因有三点,我一个个说。

第一,数据规模变了。以前数仓里跑的是GB级数据,全量重刷还能接受。现在数据湖里动不动就PB级,你每天全量跑一次?存储和计算成本都扛不住。我见过一个客户,每天全量跑一次订单表,光存储开销就占了预算的40%。改成增量后,直接降到5%。

第二,时效性要求变了。实时报表、实时风控、实时推荐——业务方要的是分钟级甚至秒级的数据。全量批处理跑一次要几小时,黄花菜都凉了。增量计算可以做到「数据一到就处理」,延迟大幅降低。

第三,湖仓一体的技术底座成熟了。以前做增量计算,难点在于「怎么保证增量数据不丢不重」。传统数据湖没有事务支持,增量处理很容易出问题。现在Delta Lake、Iceberg这些技术提供了Change Data Feed、增量查询等能力,让增量计算有了可靠的基础。

增量计算的核心价值:

  • 降低存储成本:只处理变化的数据,避免全量冗余
  • 降低计算成本:减少重复计算,提升资源利用率
  • 提升时效性:从T+1走向近实时
  • 支持流批一体:同一套逻辑,批处理和流处理都能跑

下面这张图展示了从数据仓库到湖仓一体的演进脉络,以及增量计算在其中扮演的角色:

数据架构演进与增量计算的位置 数据仓库 Schema on Write 强事务 · 高成本 全量批处理为主 数据湖 Schema on Read 低成本 · 高灵活 无事务 · 易沼泽化 湖仓一体 ACID事务 Schema演进 流批一体 增量计算:湖仓一体的核心能力 Change Data Capture · 增量查询 · 流式处理 · 时间旅行 为什么增量计算成为刚需? ① 数据规模从GB→PB,全量重刷成本不可接受 ② 时效性要求从T+1→分钟级,批处理无法满足 ③ 湖仓技术(Delta/Iceberg/Hudi)提供了可靠的事务基础

1.6 增量计算的技术基础:CDC与增量查询

增量计算要落地,离不开两个关键技术:CDC(Change Data Capture)和增量查询。

CDC负责捕获数据的变化。常见的手段有:

  • 数据库日志解析(如Debezium读取MySQL binlog)
  • 时间戳对比(通过last_modified字段识别变化)
  • 触发器/审计表(数据库层面记录变更)
  • 应用层双写(业务代码同时写主库和消息队列)

增量查询则是在湖仓引擎层面,只读取变化的数据。以Apache Iceberg为例:

-- Iceberg 增量查询:只读取指定时间范围内的变更
SELECT * FROM orders 
FOR SYSTEM_VERSION AS OF '2024-01-15 10:00:00'
WHERE _change_type IN ('INSERT', 'UPDATE', 'DELETE')
  AND _committed_at BETWEEN '2024-01-15 09:00:00' AND '2024-01-15 10:00:00'

我个人习惯把增量计算分为三个层次:

  1. 存储层增量:文件级别的增量写入,避免全量覆盖
  2. 计算层增量:只处理变化的分区或文件,不做全表扫描
  3. 应用层增量:业务逻辑只关注新增/变更的数据,不重算历史

避坑指南:我曾经在一个项目中,CDC采集的binlog数据直接写入数据湖,结果发现源库的一次DDL操作(加字段)导致下游所有增量任务报错。后来我养成了一个习惯——所有CDC管道必须做Schema兼容性校验,不兼容的变更要自动告警并暂停写入。

1.7 小结:增量计算不是可选项,是必选项

从数据仓库到数据湖,再到湖仓一体,这条演进路线背后有一个清晰的逻辑:数据架构越来越灵活,但灵活的前提是可控。增量计算就是那个「可控」的关键——它让你既能享受数据湖的低成本存储,又能获得数据仓库的事务保障。

接下来的章节,我会深入讲解增量计算在数据湖中的具体实现技术,包括Delta Lake的增量读写、Iceberg的增量查询优化、以及流批一体架构的设计模式。这些内容都是我这些年摸爬滚打总结出来的实战经验,希望能帮你少走弯路。