Iceberg从入门到精通系列之十八:一篇文章深入了解Flink对Iceberg的支持

Apache Iceberg 支持 Apache Flink 的 DataStream API 和 Table API。

一、Flink支持的iceberg功能

功能支持 Flink 注意事项
SQL create catalog ✔️
SQL create database ✔️
SQL create table ✔️
SQL create table like ✔️
SQL alter table ✔️ 仅支持更改表属性,不支持列和分区更改
SQL drop_table ✔️
SQL select ✔️ 支持流式和批处理模式
SQL insert into ✔️ 支持流式和批处理模式
SQL insert overwrite ✔️
DataStream read ✔️
DataStream append ✔️
DataStream overwrite ✔️
Metadata tables ✔️
Rewrite files action ✔️

二、使用Flink SQL Client时的准备

在 Flink 中创建 Iceberg 表,建议使用 Flink SQL Client,这样用户更容易理解概念。

从 Apache 下载页面下载 Flink。 Iceberg 在编译 Apache Iceberg-flink-runtime jar 时使用 Scala 2.12,因此建议使用与 Scala 2.12 捆绑在一起的 Flink 1.16。

FLINK_VERSION=1.16.1
SCALA_VERSION=2.12
APACHE_FLINK_URL=https://archive.apache.org/dist/flink/
wget ${APACHE_FLINK_URL}/flink-${FLINK_VERSION}/flink-${FLINK_VERSION}-bin-scala_${SCALA_VERSION}.tgz
tar xzvf flink-${FLINK_VERSION}-bin-scala_${SCALA_VERSION}.tgz

在 Hadoop 环境中启动独立的 Flink 集群:

# HADOOP_HOME is your hadoop root directory after unpack the binary package.
APACHE_HADOOP_URL=https://archive.apache.org/dist/hadoop/
HADOOP_VERSION=2.8.5
wget ${APACHE_HADOOP_URL}/common/hadoop-${HADOOP_VERSION}/hadoop-${HADOOP_VERSION}.tar.gz
tar xzvf hadoop-${HADOOP_VERSION}.tar.gz
HADOOP_HOME=`pwd`/hadoop-${HADOOP_VERSION}

export HADOOP_CLASSPATH=`$HADOOP_HOME/bin/hadoop classpath`

# Start the flink standalone cluster
./bin/start-cluster.sh

启动 Flink SQL 客户端。 Iceberg项目中有一个单独的flink-runtime模块来生成捆绑的jar,可以直接由Flink SQL客户端加载。要手动构建 flink-runtime 捆绑的 jar,请构建 Iceberg 项目,它将在 <iceberg-root-dir>/flink-runtime/build/libs 下生成 jar。或者从 Apache 存储库下载 flink-runtime jar。

# HADOOP_HOME is your hadoop root directory after unpack the binary package.
export HADOOP_CLASSPATH=`$HADOOP_HOME/bin/hadoop classpath`   

./bin/sql-client.sh embedded -j <flink-runtime-directory>/iceberg-flink-runtime-1.16-1.3.0.jar shell

默认情况下,Iceberg 附带用于 Hadoop 目录的 Hadoop jar。要使用 Hive 目录,请在打开 Flink SQL 客户端时加载 Hive jar。幸运的是,Flink 为 SQL 客户端提供了捆绑的 Hive jar。有关如何下载依赖项并开始使用的示例:

# HADOOP_HOME is your hadoop root directory after unpack the binary package.
export HADOOP_CLASSPATH=`$HADOOP_HOME/bin/hadoop classpath`

ICEBERG_VERSION=1.3.0
MAVEN_URL=https://repo1.maven.org/maven2
ICEBERG_MAVEN_URL=${MAVEN_URL}/org/apache/iceberg
ICEBERG_PACKAGE=iceberg-flink-runtime
wget ${ICEBERG_MAVEN_URL}/${ICEBERG_PACKAGE}-${FLINK_VERSION_MAJOR}/${ICEBERG_VERSION}/${ICEBERG_PACKAGE}-${FLINK_VERSION_MAJOR}-${ICEBERG_VERSION}.jar -P lib/

HIVE_VERSION=2.3.9
SCALA_VERSION=2.12
FLINK_VERSION=1.16.1
FLINK_CONNECTOR_URL=${MAVEN_URL}/org/apache/flink
FLINK_CONNECTOR_PACKAGE=flink-sql-connector-hive
wget ${FLINK_CONNECTOR_URL}/${FLINK_CONNECTOR_PACKAGE}-${HIVE_VERSION}_${SCALA_VERSION}/${FLINK_VERSION}/${FLINK_CONNECTOR_PACKAGE}-${HIVE_VERSION}_${SCALA_VERSION}-${FLINK_VERSION}.jar

./bin/sql-client.sh embedded shell

三、Flink’s Python API

使用 pip 安装 Apache Flink 依赖项:

pip install apache-flink==1.16.1

提供iceberg-flink-runtime jar的file://路径,可以通过构建项目并查看/flink-runtime/build/libs获得,或者从Apache官方下载存储库。第三方 jar 可以通过以下方式添加到 pyflink:

  • env.add_jars(“文件:///my/jar/path/connector.jar”)
  • table_env.get_config().get_configuration().set_string(“pipeline.jars”, “file:///my/jar/path/connector.jar”)

官方文档中也提到了这一点。下面的示例使用 env.add_jars(…):

import os

from pyflink.datastream import StreamExecutionEnvironment

env = StreamExecutionEnvironment.get_execution_environment()
iceberg_flink_runtime_jar = os.path.join(os.getcwd(), "iceberg-flink-runtime-1.16-1.3.0.jar")

env.add_jars("file://{}".format(iceberg_flink_runtime_jar))

接下来,创建StreamTableEnvironment并执行Flink SQL语句。以下示例展示了如何通过 Python Table API 创建自定义目录:

from pyflink.table import StreamTableEnvironment
table_env = StreamTableEnvironment.create(env)
table_env.execute_sql("""
CREATE CATALOG my_catalog WITH (
    'type'='iceberg', 
    'catalog-impl'='com.my.custom.CatalogImpl',
    'my-additional-catalog-config'='my-value'
)
""")

运行查询:

(table_env
    .sql_query("SELECT PULocationID, DOLocationID, passenger_count FROM my_catalog.nyc.taxis LIMIT 5")
    .execute()
    .print()) 
+----+----------------------+----------------------+--------------------------------+
| op |         PULocationID |         DOLocationID |                passenger_count |
+----+----------------------+----------------------+--------------------------------+
| +I |                  249 |                   48 |                            1.0 |
| +I |                  132 |                  233 |                            1.0 |
| +I |                  164 |                  107 |                            1.0 |
| +I |                   90 |                  229 |                            1.0 |
| +I |                  137 |                  249 |                            1.0 |
+----+----------------------+----------------------+--------------------------------+
5 rows in set

四、添加目录。

Flink 支持使用 Flink SQL 创建目录。

目录配置

通过执行以下查询来创建和命名目录(将 <catalog_name> 替换为您的目录名称,将 <config_key>=<config_value> 替换为目录实现配置):

CREATE CATALOG <catalog_name> WITH (
  'type'='iceberg',
  `<config_key>`=`<config_value>`
); 

以下属性可以全局设置,并且不限于特定的目录实现:

  • type:必须是iceberg。 (必需的)
  • catalog-type:hive、hadoop 或rest 用于内置目录,或未设置以使用catalog-impl 实现自定义目录。 (选修的)
  • Catalog-impl:自定义目录实现的完全限定类名。如果未设置目录类型,则必须设置。 (选修的)
  • property-version:描述属性版本的版本号。如果属性格式发生更改,此属性可用于向后兼容。当前属性版本为1。(可选)
  • cache-enabled:是否启用目录缓存,默认值为true。 (选修的)
  • cache.expiration-interval-ms:目录条目在本地缓存多长时间,以毫秒为单位;负值如 -1 将禁用过期,值 0 不允许设置。默认值为-1。 (选修的)

五、Hive catalog

这将创建一个名为 hive_catalog 的 Iceberg 目录,可以使用 ‘catalog-type’=‘hive’ 进行配置,该目录从 Hive 元存储加载表:

CREATE CATALOG hive_catalog WITH (
  'type'='iceberg',
  'catalog-type'='hive',
  'uri'='thrift://localhost:9083',
  'clients'='5',
  'property-version'='1',
  'warehouse'='hdfs://nn:8020/warehouse/path'
);

如果使用 Hive 目录,可以设置以下属性:

  • uri:Hive 元存储的 Thrift URI。 (必需的)
  • client:Hive Metastore 客户端池大小,默认值为 2。(可选)
  • warehouse:Hive仓库位置,如果既没有设置hive-conf-dir来指定包含hive-site.xml配置文件的位置,也没有在classpath中添加正确的hive-site.xml,则应指定此路径。
  • hive-conf-dir:包含 hive-site.xml 配置文件的目录路径,该文件将用于提供自定义 Hive 配置值。如果同时设置 hive-conf-dir 和仓库,则 /hive-site.xml(或类路径中的 hive 配置文件)中的 hive.metastore.warehouse.dir 值将被仓库值覆盖创建iceberg目录。
  • hadoop-conf-dir:包含 core-site.xml 和 hdfs-site.xml 配置文件的目录路径,这些文件将用于提供自定义 Hadoop 配置值。

创建表

CREATE TABLE `hive_catalog`.`default`.`sample` (
    id BIGINT COMMENT 'unique id',
    data STRING
);

写数据

要将新数据附加到具有 Flink 流作业的表中,请使用 INSERT INTO:

INSERT INTO `hive_catalog`.`default`.`sample` VALUES (1, 'a');
INSERT INTO `hive_catalog`.`default`.`sample` SELECT id, data from other_kafka_table;

要将表中的数据替换为查询结果,请在批处理作业中使用 INSERT OVERWRITE(flink 流作业不支持 INSERT OVERWRITE)。覆盖是 Iceberg 表的原子操作。

具有 SELECT 查询生成的行的分区将被替换,例如:

INSERT OVERWRITE `hive_catalog`.`default`.`sample` VALUES (1, 'a');

Iceberg 还支持通过选择值覆盖给定分区:

INSERT OVERWRITE `hive_catalog`.`default`.`sample` PARTITION(data='a') SELECT 6;

Flink 原生支持将 DataStream 和 DataStream 写入iceberg表。

StreamExecutionEnvironment env = ...;

DataStream<RowData> input = ... ;
Configuration hadoopConf = new Configuration();
TableLoader tableLoader = TableLoader.fromHadoopTable("hdfs://nn:8020/warehouse/path", hadoopConf);

FlinkSink.forRowData(input)
    .tableLoader(tableLoader)
    .append();

env.execute("Test Iceberg DataStream");

分支写入

FlinkSink 中的 toBranch API 还支持写入 Iceberg 表中的分支。

FlinkSink.forRowData(input)
    .tableLoader(tableLoader)
    .toBranch("audit-branch")
    .append();


使用以下语句提交 Flink 批处理作业:

-- Execute the flink job in batch mode for current session context
SET execution.runtime-mode = batch;
SELECT * FROM `hive_catalog`.`default`.`sample`;

Iceberg 支持处理从历史快照 ID 开始的 Flink 流作业中的增量数据:

-- Submit the flink job in streaming mode for current session.
SET execution.runtime-mode = streaming;

-- Enable this switch because streaming read SQL will provide few job options in flink SQL hint options.
SET table.dynamic-table-options.enabled=true;

-- Read all the records from the iceberg current snapshot, and then read incremental data starting from that snapshot.
SELECT * FROM `hive_catalog`.`default`.`sample` /*+ OPTIONS('streaming'='true', 'monitor-interval'='1s')*/ ;

-- Read all incremental data starting from the snapshot-id '3821550127947089987' (records from this snapshot will be excluded).
SELECT * FROM `hive_catalog`.`default`.`sample` /*+ OPTIONS('streaming'='true', 'monitor-interval'='1s', 'start-snapshot-id'='3821550127947089987')*/ ;

SQL 也是检查表的推荐方法。要查看表中的所有快照,请使用快照元数据表:

SELECT * FROM `hive_catalog`.`default`.`sample`.`snapshots`

Iceberg支持Java API中的流式或批量读取:

DataStream<RowData> batch = FlinkSource.forRowData()
     .env(env)
     .tableLoader(tableLoader)
     .streaming(false)
     .build();

六、类型转换

Iceberg 对 Flink 的集成会自动在 Flink 和 Iceberg 类型之间进行转换。当写入 Flink 不支持的类型(例如 UUID)的表时,Iceberg 将接受并转换 Flink 类型的值。

Flink 到 Iceberg

Flink 类型按照下表转换为 Iceberg 类型:

Flink Iceberg Notes
boolean boolean
tinyint integer
smallint integer
integer integer
bigint long
float float
double double
char string
varchar string
string string
binary binary
varbinary fixed
decimal decimal
date date
time time
timestamp timestamp without timezone
timestamp_ltz timestamp with timezone
array list
map map
multiset map
row struct
raw Not supported
interval Not supported
structured Not supported
timestamp with zone Not supported
distinct Not supported
null Not supported
symbol Not supported
logical Not supported

Iceberg to Flink

Iceberg 类型按照下表转换为 Flink 类型:

Iceberg Flink
boolean boolean
struct row
list array
map map
integer integer
long bigint
float float
double double
date date
time time
timestamp without timezone timestamp(6)
timestamp with timezone timestamp_ltz(6)
string varchar(2147483647)
uuid binary(16)
fixed(N) binary(N)
binary varbinary(2147483647)
decimal(P, S) decimal(P, S)

七、待支持的功能

目前的 Flink Iceberg 集成工作尚不支持一些功能:

  • 不支持创建隐藏分区的Iceberg表
  • 不支持创建带有计算列的Iceberg表
  • 不支持创建带水印的Iceberg表
  • 不支持添加列、删除列、重命名列、更改列,会在flink 1.18.0版本中支持

猜你喜欢

转载自blog.csdn.net/zhengzaifeidelushang/article/details/131745396