数据湖 Iceberg
目前比较流行的开源数据湖 Iceberg。
最近在梳理大数据存储方案时,绕不开"数据湖"这个词。业务数据早已不只是关系型数据库里的表:埋点日志、JSON 报文、图片音视频,各种形态的数据都要有个地方落。传统数仓在这类场景下越来越吃力,而围绕数据湖的一批开源项目正好补上了这个缺口。这篇就把数据湖与数仓的区别、以及其中比较有代表性的 Iceberg 简单整理一下,作为自己的学习笔记。
数据湖与数据仓库
数据湖是一个用于存储结构化和非结构化数据的集中式数据存储库,它可以存储各种类型的数据,包括传统的关系型数据、半结构化数据、非结构化数据等。数据湖的主要特点是具有高度的灵活性和可扩展性,能够方便地进行数据的存储和处理。
数据湖的一个核心理念是"先存后管"(schema-on-read):数据以原始格式写入廉价的分布式存储(如 HDFS 或对象存储),到真正分析时才去解析结构。这和数仓"先建模后入库"(schema-on-write)的思路正好相反,也是它能兼容各种数据形态的原因。
相比之下,传统的数据仓库主要用于存储结构化数据,它们通常采用关系型数据库进行存储和管理。数据仓库的主要特点是具有高度的规范化和结构化,能够保证数据的准确性和一致性。但是,数据仓库的缺点在于它们不够灵活,无法存储和处理非结构化或半结构化数据,而且难以进行扩展和升级。
数据湖相比数据仓库的优势主要有以下几点:
- 存储不受限制:数据湖可以存储各种类型的数据,包括传统的结构化数据、半结构化数据、非结构化数据等。这使得数据湖更加灵活,适用于不同类型和规模的数据存储需求。
- 处理速度更快:数据湖通常采用分布式存储和计算技术,能够实现高速数据处理和分析。而传统的数据仓库则往往需要进行多次数据转换和计算,导致处理速度较慢。
- 成本更低:数据湖通常采用开源技术,如Hadoop、Spark等,成本相对较低,而传统的数据仓库则需要采用商业数据库软件,成本较高。
- 更加灵活:数据湖具有更高的灵活性,能够方便地进行数据的存储和处理。而传统的数据仓库则往往需要进行多次数据转换和计算,导致数据处理过程变得复杂和困难。
当然,灵活是有代价的。裸的数据湖只是一堆文件目录,缺少事务、缺少模式约束,写入方和读取方稍不注意就会互相踩踏,时间一长很容易变成"数据沼泽"。表格式(table format)这一层抽象就是为了解决这个问题——在文件之上定义出"表"的语义,Iceberg 正是这一类项目。
Apache Iceberg
Iceberg是一个开源的数据表格式和处理库,它旨在解决数据湖中数据表的管理和处理问题。Iceberg是由Netflix开发的,目前已经成为Apache软件基金会的顶级项目之一。
Iceberg解决了传统数据湖中的一些问题,例如数据表的版本控制、数据表的元数据管理、数据分区管理、数据表的快照管理等。Iceberg支持多种数据存储和处理系统,包括Hadoop、Spark、Presto、Flink等。
这里值得展开说一下它的工作机制。Iceberg 本身不存数据,数据仍然是 Parquet、ORC 这类列存文件;它管理的是数据之上的元数据层。元数据大致分三级:
- 快照(snapshot):表在某一时刻的完整状态,每次写入提交都会生成一个新快照,旧快照依然可读。
- 清单列表与清单文件(manifest list / manifest):记录快照包含哪些数据文件,以及每个文件的分区范围、行数、列级统计等信息。
- 数据文件:真正的列存文件,元数据只引用、不修改它们。
写入时新元数据先落盘,最后通过一次对表指针的原子替换完成提交,这就让文件系统之上有了类似数据库的 ACID 语义。查询时引擎先读元数据,利用其中的统计信息跳过无关文件,而不必像 Hive 那样去 List 整个目录——在对象存储上,这一点对性能影响很大。
Iceberg 的主要特点
Iceberg 的主要特点有:
- 数据表版本控制:Iceberg支持数据表版本控制,可以对数据表进行版本管理和控制。用户可以轻松地回滚到历史版本,或者将不同版本的数据表进行合并。
- 数据表元数据管理:Iceberg提供了一种元数据管理机制,可以方便地对数据表进行管理和查询。用户可以通过元数据来了解数据表的结构、分区、数据统计等信息。
- 数据分区管理:Iceberg支持多种分区方式,包括哈希分区、范围分区、哈希范围混合分区等。用户可以根据自己的需求选择不同的分区方式。
- 数据表快照管理:Iceberg支持对数据表进行快照管理,可以轻松地进行数据备份和恢复。
分区这一点还有个细节:Iceberg 的分区是"隐藏分区"。分区值由列值通过转换函数(比如按天截断时间戳)自动推导,查询时直接用原始列写过滤条件即可,引擎会自动利用分区裁剪。写查询的人不需要知道表是怎么分区的,这比 Hive 里手动维护分区列的方式友好不少。分区规则本身也可以演进,改规则不需要重写历史数据。
模式演进(schema evolution)同样是它的强项:加列、删列、改名都只改元数据,列通过唯一 ID 而不是名字或位置来跟踪,避免了老式表格式里改个列名就可能读错数据的问题。
踩坑与注意
- 小文件问题依然存在。流式写入频率高时会产生大量小数据文件和元数据文件,需要定期跑合并(compaction),否则查询性能会持续劣化。
- 快照不会自动清理。每次提交都留一个快照,历史快照引用的文件不会被删除,长期不做快照过期处理,存储会越积越多。
- Catalog 选型要先想清楚。Iceberg 的表指针需要一个 catalog 来管理(Hive Metastore、JDBC 等都可以),不同引擎要访问同一张表,得共用同一套 catalog,迁移起来比较麻烦。
- 同类项目还有 Delta Lake 和 Apache Hudi,三者定位相近但生态侧重不同,选型前最好结合自己主用的计算引擎做对比,不必默认跟风。
小结
数据湖解决的是"什么数据都能存"的问题,但只有存储没有管理,湖很容易变成沼泽。Iceberg 这类表格式在文件之上补齐了事务、版本、分区和模式管理,让数据湖具备了接近数仓的表语义,同时保留了开放格式和低成本的优势。对我来说,理解它的关键在于那三层元数据结构——想明白快照和清单文件是怎么组织的,回滚、时间旅行、分区裁剪这些能力也就顺理成章了。后面有机会再单独记录在 Flink / Spark 上实际读写 Iceberg 表的过程。
评论 / COMMENTS