1. Iceberg 前世今生:数据湖演进、Iceberg 诞生背景、核心设计理念

聊 Iceberg 之前,我想先聊聊数据湖。这玩意儿现在听起来很平常,但十年前可不是这样。我入行那会儿,大家还在为「数据仓库到底要不要上 Hadoop」争得面红耳赤。嗯,现在回头看,那段历史挺有意思的。

1.1 数据湖的演进:从 HDFS 到开放架构

数据湖这个概念,最早是 2010 年左右冒出来的。说白了,就是想解决一个核心问题:数据仓库太贵、太死板。

传统数仓要求你先建模,再灌数据。但现实是,业务变化太快,你根本不知道明天会冒出什么新字段。我经历过一个项目,业务方临时要加一个用户行为标签,数仓那边排期排了两周。两周啊,黄花菜都凉了。

所以数据湖的初衷很简单:先把数据存下来,格式不限,后面再说。HDFS 成了首选,便宜、能存、能算。

但很快问题就暴露了。我列几个典型的痛点:

  • 文件管理混乱:HDFS 上全是目录和文件,没有表的概念。你要查一个「用户表」,得自己拼路径。
  • ACID 缺失:写入一半挂了,数据可能就坏了。没有事务,没有回滚。
  • 性能瓶颈:Hive 查个小表都要全表扫描,慢得让人抓狂。
  • 数据质量差:没有 schema 约束,脏数据随便往里写,查出来全是坑。

那段时间,我经常听到一句话:「数据湖就是个数据沼泽。」说实话,挺形象的。

后来社区开始想办法。Hive 出了 ACID,但性能太差。Spark 出了 Delta Lake,但绑定 Spark 生态。AWS 出了 Lake Formation,但绑定云。每个方案都有局限。

直到 2017 年,Netflix 和 Airbnb 分别开源了 Iceberg 和 Hudi。2018 年,Databricks 开源了 Delta Lake。这三个项目,后来被称为「数据湖三剑客」。它们的目标一致:让数据湖拥有数据库一样的能力。

核心变化:从「存文件」到「管表」。数据湖不再是一堆散乱的文件,而是有 schema、有事务、有快照的「表」。

1.2 Iceberg 的诞生背景:Netflix 的痛点

Iceberg 是 Netflix 搞出来的。为什么是 Netflix?因为他们数据量大、场景复杂、对性能要求极高。

我记得看过 Netflix 的技术分享,他们当时用 Hive 管理 PB 级数据,遇到几个要命的问题:

  • 分区演进困难:Hive 的分区是物理目录,改分区策略要重写所有数据。
  • 快照管理缺失:没有时间旅行,查历史数据得靠备份。
  • 并发写入冲突:多个任务同时写一个表,经常出问题。
  • 查询性能不稳定:同样的 SQL,今天跑 10 秒,明天跑 10 分钟。

Netflix 试过自己改 Hive,但 Hive 的架构太老了,改不动。于是他们决定从头写一个表格式。2017 年开源,2018 年捐给 Apache 基金会,2020 年成为顶级项目。

我自己的经历也类似。2020 年我在一个金融项目里,用 Hive 管交易数据。每天凌晨跑批,经常因为文件冲突挂掉。后来切到 Iceberg,这些问题基本消失了。嗯,说实话,当时真有种「相见恨晚」的感觉。

个人建议:如果你还在用 Hive 管理关键业务数据,强烈建议试试 Iceberg。尤其是那些对数据一致性要求高的场景。

1.3 核心设计理念:Iceberg 凭什么不一样

Iceberg 的设计理念,可以用三个词概括:开放、高效、可靠。

咱们一个一个说。

1.3.1 开放:不绑定任何引擎

这是 Iceberg 和 Delta Lake 最大的区别。Delta Lake 是 Databricks 的,虽然也开源,但底层和 Spark 深度绑定。Iceberg 从一开始就设计成「引擎无关」。

什么意思?就是你可以用 Spark 写,用 Flink 读,用 Trino 查,用 Hive 跑批。所有引擎共享同一份元数据,同一份数据文件。

我见过一个团队,数据写入用 Flink,批处理用 Spark,查询用 Trino。三个引擎同时操作同一张 Iceberg 表,完全没问题。这在以前想都不敢想。

1.3.2 高效:快照 + 分区裁剪 + 隐式分区

Iceberg 的高效,体现在几个关键设计上:

  • 快照机制:每次写入生成一个新快照,查询只读快照,读写不互斥。
  • 分区裁剪:元数据里记录了每个分区的文件范围,查询时直接跳过无关分区。
  • 隐式分区:不用手动管理分区目录,Iceberg 自动根据分区字段组织数据。

举个例子。一张订单表按日期分区,查询某一天的数据。Hive 会扫描所有分区目录,Iceberg 直接定位到那天的文件。差距有多大?我测过,10TB 的表,查询时间从 5 分钟降到 10 秒。

1.3.3 可靠:ACID + Schema 演进 + 时间旅行

Iceberg 提供了完整的 ACID 事务。写入要么全部成功,要么全部回滚。不会出现「写了一半,数据坏了」的情况。

Schema 演进也很方便。加字段、删字段、改字段类型,都支持。而且不会影响历史数据。我有个项目,业务方要求加一个「渠道来源」字段。以前用 Hive,得重建表、重刷数据。用 Iceberg,一行 ALTER TABLE 搞定。

时间旅行就更实用了。查历史数据、做数据回滚、审计追溯,都靠它。我曾经用它排查过一个数据问题:某天跑批结果异常,直接查前一天的快照,对比差异,半小时定位到 bug。

注意:时间旅行不是无限保留的。Iceberg 默认只保留最近几个快照,过期的会被清理。你需要根据业务需求配置保留策略。

1.4 核心架构:一张图看懂 Iceberg

下面这张图,是我自己画的 Iceberg 核心架构。它展示了数据、元数据、引擎之间的关系。

Iceberg 核心架构图 Iceberg 核心架构 计算引擎层(Spark / Flink / Trino / Hive / Presto) 元数据层(Metadata Layer) 快照(Snapshot)→ 清单列表(Manifest List)→ 清单文件(Manifest) 数据层(Data Layer) Parquet / ORC / Avro 数据文件(Data Files) 存储层(HDFS / S3 / OSS / GCS) 引擎通过元数据层定位数据文件,元数据层管理快照和分区信息,数据文件存储在底层文件系统

这张图展示了 Iceberg 的四层架构。从上到下依次是:

  1. 计算引擎层:Spark、Flink、Trino 等。它们通过 Iceberg 的 API 读写数据。
  2. 元数据层:Iceberg 的核心。管理快照、清单列表、清单文件。查询时先读元数据,再定位数据文件。
  3. 数据层:实际的数据文件。Parquet、ORC、Avro 格式都支持。
  4. 存储层:底层文件系统。HDFS、S3、OSS、GCS 都可以。

注意一个关键点:元数据层和数据层是分离的。这意味着你可以独立管理元数据,不用动数据文件。这也是 Iceberg 支持 Schema 演进和时间旅行的基础。

1.5 核心概念速览

为了让你快速上手,我把 Iceberg 的几个核心概念整理成了一张表:

概念 说明 类比
Table 一张逻辑表,包含 schema、分区、快照等信息 数据库中的表
Snapshot 表在某个时间点的完整数据视图 Git 的 commit
Manifest List 快照包含的所有清单文件的列表 目录索引
Manifest 一组数据文件的元数据信息 分区内的文件清单
Data File 实际存储数据的文件(Parquet/ORC/Avro) 数据行
Partition 按字段划分的数据子集,用于查询裁剪 文件夹

避坑指南:我曾经犯过一个错误——把 Iceberg 的「快照」理解成数据库的「快照」。其实不一样。Iceberg 的快照是增量式的,只记录变化的部分,不是全量复制。所以快照很轻量,生成很快。

1.6 为什么选择 Iceberg?

最后,我想说说我的个人选择。市面上有 Delta Lake、Hudi、Iceberg 三个主流方案,为什么我推荐 Iceberg?

  • 开放生态:不绑定任何引擎,未来不会被厂商锁定。
  • 社区活跃:Apache 顶级项目,贡献者来自 Netflix、Apple、腾讯、阿里等大厂。
  • 性能优秀:分区裁剪、快照隔离、隐式分区,查询效率远超 Hive。
  • 成熟稳定:已经在 Netflix、Apple、腾讯等公司生产环境运行多年。

当然,没有银弹。Iceberg 也有缺点:元数据管理有额外开销,小文件场景需要优化,学习曲线比 Hive 陡一些。但总体来说,利远大于弊。