Lakehouse 核心概念:定义、ACID 事务与 Schema 哲学

好,我们正式开始聊 Lakehouse 的核心概念。这一节我把它看作整个课程的“地基”。地基打不牢,后面盖楼心里发虚。我个人习惯,学一个新架构,先抓住三个东西:它到底是什么、它凭什么敢说自己“可靠”、它怎么处理数据。

说白了,Lakehouse 不是凭空冒出来的。它想解决一个很现实的问题:数据湖便宜、能存一切,但数据质量一塌糊涂;数据仓库质量高、查询快,但贵得要命,还存不了非结构化数据。Lakehouse 就是那个“我全都要”的方案。

1. 到底什么是 Lakehouse?

我自己的定义很简单:Lakehouse = 数据湖的存储 + 数据仓库的治理能力。它直接在廉价的对象存储(比如 S3、OSS、HDFS)上,加了一层事务、索引、缓存和 SQL 引擎。你想想看,数据不用来回搬了,一份数据既能跑机器学习,又能做 BI 报表。

嗯,这里要注意,Lakehouse 不是某个具体产品。它是一种架构模式。Delta Lake、Apache Iceberg、Apache Hudi 都是它的具体实现。我在项目中遇到过不少团队,上来就问“我们用哪个 Lakehouse 产品?”,其实更应该先问“我们的数据场景需要 ACID 吗?需要实时 Upsert 吗?”

核心特征总结:

  • 同一份存储,支持批、流、交互式查询
  • 事务支持(ACID),保证数据一致性
  • 开放格式(Parquet/ORC),不被厂商锁定
  • Schema 灵活演化,适应多变业务

下面这张图,是我每次给团队做培训时必画的。它把 Lakehouse 在技术栈里的位置讲清楚了。

Lakehouse 架构分层图 Lakehouse 核心架构分层 BI 工具 / 数据科学 / ML 训练 查询引擎(Spark / Presto / Flink) Lakehouse 核心层 ACID 事务 | Schema 管理 | 索引 | 时间旅行 开放文件格式(Parquet / ORC / Avro) 对象存储(S3 / OSS / HDFS) 数据流向

2. ACID 事务:Lakehouse 的“定海神针”

为什么传统数据湖被人诟病?最痛的一点就是“读到一半,数据变了”。你跑个报表,结果读到的是半成品。这在数据仓库里几乎不会发生,因为有事务隔离。

Lakehouse 把 ACID 带到了对象存储上。我简单解释一下这四个属性:

属性 含义 在 Lakehouse 中的体现
原子性 事务要么全做,要么全不做 写入一批数据,中途失败自动回滚,不会出现“半份文件”
一致性 事务前后,数据约束不被破坏 Schema 校验、约束检查在提交时强制执行
隔离性 并发事务互不干扰 快照隔离(Snapshot Isolation),读不阻塞写
持久性 提交的数据不会丢失 事务日志写入可靠存储,可恢复

我的经验: 曾经有个实时数仓项目,ETL 任务在凌晨 3 点频繁失败,导致报表数据错乱。排查了一周,发现是并发写入同一个分区时,没有事务保护。后来切到 Delta Lake,开启 ACID,问题直接消失。说白了,没有事务的数据湖,就是“数据沼泽”。

ACID 的实现原理,核心是事务日志(Transaction Log)。每次数据变更,不是直接改文件,而是先写一条日志。查询时,引擎只读取“已提交”的版本。这就实现了时间旅行(Time Travel)——你可以查询任意历史版本的数据。

-- 示例:Delta Lake 的时间旅行查询
-- 查询 30 分钟前的数据快照
SELECT * FROM my_table TIMESTAMP AS OF '2025-01-15T10:00:00';

-- 或者按版本号查询
SELECT * FROM my_table VERSION AS OF 123;

3. Schema-on-Read vs Schema-on-Write

这两个概念,我刚开始接触时也绕了一阵。简单说:

  • Schema-on-Write:数据写入时,必须符合预定义的结构。不符合?写入失败。这是数据仓库的做法。
  • Schema-on-Read:数据先存进去,结构随便。读取时,由查询引擎现场解析。这是传统数据湖的做法。

你想想看,数据湖为什么灵活?因为它不限制写入格式。但代价是什么?查询时可能发现字段对不上、类型不匹配,跑出来的结果乱七八糟。

Lakehouse 走的是中间路线:写入时做轻量校验(比如文件格式必须合法),但不强制全量 Schema;读取时提供强类型推断和 Schema 演化。说白了,它把“写时检查”和“读时灵活”结合起来了。

避坑指南: 我曾经见过一个团队,把所有 JSON 日志原封不动扔进数据湖,字段嵌套了 7 层,有的字段名还带空格。查询时 Spark 直接 OOM。后来我强制要求:写入时至少做一层 Schema 推断,嵌套不超过 3 层。记住,Schema-on-Read 不是“无 Schema”,而是“延迟绑定”。

下面这个对比表,我建议你收藏。面试时经常被问到。

维度 Schema-on-Write Schema-on-Read Lakehouse 做法
写入性能 较慢(需要校验) 极快(不校验) 中等(轻量校验 + 事务日志)
查询性能 快(结构已知) 较慢(需要推断) 快(有索引和统计信息)
灵活性 低 高 高(支持 Schema 演化)
数据质量 高 低 高(ACID + 约束)
典型场景 数据仓库、金融报表 日志收集、原始数据探索 混合负载、ML + BI

4. Schema 演化:别让结构绑死你

业务变了,字段要加。这在传统数据仓库里是个大工程——先 Alter Table,再重写历史数据。Lakehouse 支持Schema 演化,加字段、改类型、甚至重命名,都可以在线完成,不用停服务。

我举个例子。你在 Delta Lake 里加一个字段:

-- 允许 Schema 演化
ALTER TABLE sales ADD COLUMN discount DECIMAL(5,2);

-- 历史数据该字段为 NULL,新数据正常写入
-- 查询时自动处理,不会报错

嗯,这里要注意:演化不是无限制的。比如把 INT 改成 STRING 可以,但反过来可能丢精度。我在项目中定过一个规则:演化只允许“放宽”,不允许“收紧”。加字段、加长度可以;删字段、缩长度,必须走评审流程。

核心原则: Schema 演化是工具,不是借口。别因为能演化,就放弃前期设计。好的数据架构,80% 的 Schema 在第一天就应该想清楚。