Iceberg Catalog 的需求
Iceberg Catalog 的接口定义了各种 Catalog 需要实现的方法,主要包括列出存在的表,创建表,删除表,检查表是否存在,给表改名。
如果一个 Iceberg catalog 使用在生产中,主要需是原子更新当前元数据指针。因为在任意时刻,所有的读和写操作看到表的表的状态是相同的。两个并发的写入操作,第 2 个写入操作提交的时候不能覆写第 1 个写入操作对数据的修改,导致数据丢失。
各种 Iceberg Catalog 实现的比较
比较的主要维度包括:
- 是否推荐用于生产环境
- 是否需要外部系统,并且外部系统是自带的还是管理服务
- 是否和大量的引擎和工具兼容
- 是否支持多表和多语句的事务
- 是否不绑定特定的云厂商
Hadoop Catalog
Hadoop Catalog 是最简单的,不依赖外部系统。可以使用任意文件系统,包括 HDFS, S3 等。
不推荐使用在生产环境,原因如下:
- 有些文件系统 rename 操作是原子的,有些不是。像 S3 的 rename 就不是原子的。
- 仅使用数据仓库目录来列出表。如果使用对象存储,仅能使用一个 bucket。
- 如果列出 namespaces(也就是 databases) 或者 tables,当 namespaces 或者 tables 的数量比较多时,可能遇到性能问题。
- 不能仅从 catalog 删除一个表但是保留数据。
bash
spark-sql --master local[1] \
--conf spark.sql.extensions=org.apache.iceberg.spark.extensions.IcebergSparkSessionExtensions \
--conf spark.sql.catalog.my_catalog1=org.apache.iceberg.spark.SparkCatalog \
--conf spark.sql.catalog.my_catalog1.type=hadoop \
--conf spark.sql.catalog.my_catalog1.warehouse=/warehouse/tablespace/managed/hive
Hive Catalog
Hive Catalog 广泛使用。使用 Hive Metastore 中 表的属性 location 作为表的路径。
优点:
- 被多种引擎和工具支持,不依赖云厂商。
缺点:
- 需要额外的 Hive Metastore 服务。
- 不支持涉及多表操作的一致性和原子性。
The AWS Glue Catalog
使用表 metadata_location 作为表的路径。
优点:
- AWS Glue 是管理的服务,不需要像 Hive Metastore 的额外开销。
- 和其他 AWS 服务紧密集成。
缺点:
- 不支持多表事务。
- 和 AWS 生态绑定。
如果你深度购买了 AWS 的服务,并且不需要多云方案。
The Nessie Catalog
优点:
- 使数据湖像 git 一样,意味着数据和相关的元数据可以版本化,像源代码一样管理。
- 支持多表事务和多语句事务。
- 不依赖云厂商。
缺点:
- 不是所有的引擎和工具支持,当前 Spark,Flink,Dremio, Presto, Trino 和 PyIceberg 支持。
- 你必须像使用 Hive Metastore 一样,自己启动一个 Nessie。
The REST Catalog
优点:
- 比较轻量,依赖更少,简化部署和管理,因为仅仅能发送标准 HTTP 请求即可。
- 比较灵活,可以放在任意能处理 HTTP 请求的服务上,并且后端存储可以任意选择。
- 不依赖云厂商。
缺点:
- 必须运行一个服务处理 Rest 请求。
- 没有开源实现,必须自己编写。
- 不是所有的引擎和工具支持,当前 Spark,Flink,Trino 和 PyIceberg, 和 SnowFlake 支持。
The JDBC Catalog
优点:
- 容易开始。
- 数据库提供高可用性。
- 不依赖云厂商。
缺点:
- 不支持多表事务。
- 所有的引擎和工具需要 jdbc 驱动。
Catalog 迁移
使用 Catalog cli
Nessi 项目提供一个开源迁移工具。提供两个功能:迁移和注册。这两个功能都不拷贝数据。并且都支持迁移表的整个历史。
-
migrate
从旧的 catalog 迁移到新的 catalog。当迁移完成时,表就在旧的 catalog 中找不到了,是 move 操作。
-
register
register 迁移后,不删除旧的 catalog 中表定义,可以用来预迁移的验证。
使用 register,不能使用不同的 catalog 写入数据,这样会导致数据丢失。
不要在有任务使用旧 catalog 写入任务运行时进行迁移,这样会导致数据丢失。
建议小批次的迁移。
迁移命令:
bash
java -jar iceberg-catalog-iceberg-catalog-migrator-cli-0.2.0.jar migrate
使用引擎
spark 启动的时候设置两个 catalog
bash
--conf spark.sql.extensions=org.apache.iceberg.spark.extensions.IcebergSparkSessionExtensions \
--conf spark.sql.catalog.source_catalog1=org.apache.iceberg.spark.SparkCatalog \
--conf spark.sql.catalog.target_catalog1=org.apache.iceberg.spark.SparkCatalog \
--conf spark.sql.catalog.source_catalog1.xxx=xxx \
--conf spark.sql.catalog.target_catalog1.xxx=xxx \
以上命令仅启动 spark-sql。
- register_table
参数
table, metadata_file
sql
CALL target_catalog.system.register_table('table_catalog.db1.table1', '/path/to/source_catalog_warehouse/db1/table1/metadata/xxx.json')
在新 catalog 上的修改,在源 catalog 看不到。
- snapshot()
在新 catalog 上的操作,在源 catalog 看不到。反过来也一样,在源 catalog 上的操作,在新 catalog 看不到。
sql
CALL target_catalog.system.snapshot('table_catalog.db1.table1', 'target_catalog.db1.table1')