2. 核心架构对比:Iceberg的开放架构 vs Delta Lake的Spark原生架构
聊到选型,架构差异是绕不开的核心。说白了,Iceberg 和 Delta Lake 虽然都叫「湖仓一体」,但它们的基因完全不同。一个追求开放,一个拥抱原生。我当年在项目中切换过两次存储引擎,对这点感触特别深。
2.1 两种架构的设计哲学
先看一张整体对比图,帮你建立直观印象:
2.2 Iceberg:表格式规范先行
Iceberg 的核心思路很纯粹——它定义了一套开放的表格式规范。任何计算引擎,只要按照这个规范去读写数据文件,就能获得 ACID 事务和快照隔离能力。
我个人习惯把 Iceberg 比作「数据文件的 SQL 标准」。你想想看,只要你的引擎实现了 JDBC,就能连任何数据库。Iceberg 也是这个逻辑。
Iceberg 架构三要素:
- Catalog:元数据服务层,记录当前最新快照指针。支持 Hive Metastore、REST Catalog、JDBC 等。
- Metadata Layer:包含 Metadata File、Manifest List、Manifest File,形成树状结构。
- Data Layer:实际数据文件,支持 Parquet、ORC、Avro 等格式。
我在项目中遇到过一个问题:团队同时用 Spark 做批处理、Flink 做实时写入、Trino 做 Ad-hoc 查询。如果用 Delta Lake,Flink 写入的数据 Trino 读不到——因为 Trino 的 Delta Connector 版本滞后。换成 Iceberg 后,三个引擎直接读写同一张表,零适配成本。
避坑指南: 我曾经以为 Iceberg 的 REST Catalog 只是「可选组件」,结果在生产环境用 Hive Metastore 做 Catalog,遇到并发写入时元数据锁冲突严重。后来切到 REST Catalog + 独立元数据服务,问题才解决。建议你从一开始就规划好 Catalog 选型。
2.3 Delta Lake:Spark 原生的存储插件
Delta Lake 的出身决定了它的架构方向——它是 Databricks 为 Spark 量身打造的存储层。核心组件是 Transaction Log(也叫 Delta Log),以 JSON 文件形式记录每次事务变更。
Delta Lake 的架构可以概括为三层:
| 层级 | 组件 | 说明 |
|---|---|---|
| 应用层 | Spark DataFrame / SQL | 用户直接操作的 API |
| 存储层 | Delta Log + Checkpoint | 记录事务、版本、Schema 变更 |
| 文件层 | Parquet 数据文件 | 实际数据存储 |
Delta Lake 的 ACID 实现依赖 Spark 的 文件原子性 rename 操作。每次提交事务时,Spark 会原子性地写入一个新的 Delta Log 条目。如果写入失败,整个事务回滚。
注意: Delta Lake 的 Transaction Log 默认存储在文件系统(HDFS / S3)上。这意味着每次事务提交都需要一次文件 rename 操作。在对象存储(如 S3)上,rename 不是原子操作,需要额外配置 DynamoDB 并发锁。我踩过这个坑——S3 上并发写入时出现「幻读」现象,排查了两天才发现是 rename 非原子导致的。
2.4 关键差异对比表
| 对比维度 | Iceberg | Delta Lake |
|---|---|---|
| 架构本质 | 开放表格式规范 | Spark 存储插件 |
| 引擎依赖 | 无强依赖,多引擎原生 | 强依赖 Spark 运行时 |
| 元数据存储 | Catalog + Manifest 文件 | Delta Log(JSON + Checkpoint) |
| ACID 实现 | Manifest 原子替换 + 乐观锁 | Log 原子提交 + 文件 rename |
| Schema 演进 | 列级演进,无重写 | 列级演进,无重写 |
| 分区演进 | 支持隐藏分区变更 | 不支持,需重写表 |
| 时间旅行 | 基于快照 ID 或时间戳 | 基于版本号或时间戳 |
| 并发控制 | 乐观并发 + 重试机制 | 乐观并发 + 文件锁 |
2.5 选型建议:什么场景选谁?
嗯,这里要注意,没有银弹。我根据实际项目经验总结了几条原则:
- 多引擎混用场景 → Iceberg:如果你的团队同时用 Spark、Flink、Trino、Presto,Iceberg 是唯一能「零适配」的方案。
- 纯 Spark 生态 → Delta Lake:如果整个技术栈都是 Spark,Delta Lake 的集成度更高,性能优化更深入。
- 云原生对象存储 → Iceberg:Iceberg 的 Manifest 设计对 S3、OSS 更友好,没有 rename 原子性问题。
- 需要隐藏分区变更 → Iceberg:Delta Lake 不支持分区演进,一旦分区策略变了,必须重写整张表。
我的个人建议: 如果你在建设新的数据湖平台,优先考虑 Iceberg。开放架构带来的灵活性,远大于「Spark 原生」带来的性能优势。尤其是未来可能引入 Flink、Presto 等引擎时,Iceberg 的兼容性会让你少踩很多坑。
2.6 一个真实的迁移案例
最后分享一个我经手的案例。某电商平台的数据湖最初用 Delta Lake,所有任务跑在 Spark 上。后来业务需要引入 Flink 做实时写入,问题来了:
- Flink 写入 Delta Lake 需要 Delta Connector,版本必须和 Spark 集群对齐。
- Trino 查询 Delta Lake 时,部分复杂类型(如 Map、Array)解析出错。
- 并发写入时,S3 上的 rename 操作导致数据不一致。
我们花了三周时间迁移到 Iceberg。迁移后,Flink 直接写入 Iceberg 表,Trino 直接查询,Spark 继续做批处理。三个引擎读写同一张表,零冲突。嗯,这个案例让我彻底成了 Iceberg 的拥趸。