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 的四层架构。从上到下依次是:
- 计算引擎层:Spark、Flink、Trino 等。它们通过 Iceberg 的 API 读写数据。
- 元数据层:Iceberg 的核心。管理快照、清单列表、清单文件。查询时先读元数据,再定位数据文件。
- 数据层:实际的数据文件。Parquet、ORC、Avro 格式都支持。
- 存储层:底层文件系统。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 陡一些。但总体来说,利远大于弊。