所谓Catalog即数据目录,简单讲,Catalog是企业用于管理数据资产的方式,Catalog借助元数据来管理数据,包括数据收集、组织、访问、发现和治理。可见,Catalog在数据资产管理中处于核心位置。元数据本身内容非常丰富,包括技术元数据、业务元数据和操作元数据,本文仅仅研究大数据计算存储框架本身的技术元数据,比如数据库、数据表、分区、视图、函数等。限于篇幅,参与比较的计算存储框架为Flink、Iceberg和Hive,比较维度为Catalog的定义、Catalog的实现和生态拓展几个方面。
Catalog接口定义
1 Flink Catalog
从Flink Catalog的接口定义来看,Flink Catalog提供了基本的数据库、数据表、函数、视图、分区的增删改查基本操作。
2 Iceberg Catalog
从Iceberg Catalog的接口定义来看,Iceberg Catalog提供了基本的表创建、表替换、表删除、表改名和表加载、查询等操作。在对外接口参数中,Iceberg使用TableIdentifier来标识一个表,TableIdentifier内部又包含一个Namespace。在Iceberg中,一个表的完整标识组成为: TableIdentifier=Namespace+table,其中Namespace是一个字符串数组,支持多层级的表修饰,第0层为table,第1层为database。
3 Hive Catalog
Hive Catalog在3.x版本以前没有Catalog 的概念,此后的版本中才勉强在Metastore中加上了一张表,专门存储Catalog,从Hive Catalog的类定义中可见,声明是相当简单的:
private String name; // required private
String description; // optional private
String locationUri; // required
其中locationUri指定了Catalog所属的数据存储路径,该属性必填。
小结
通过Catalog定义来看,Flink Catalog功能相对完善,Iceberg Catalog跟Flink Catalog相比,没有明确的对数据库相关的操作,而且也没有像Flink Catalog那样明确的表的全名称(如用database.table来标识一个表)修饰概念,而是将表的标识概念泛化。相比Flink、Iceberg的 Catalog,Hive Catalog显得”后知后觉“,因为Hive早期设计是基于database和table两级命名来实现,也没有考虑到当前蓬勃发展的联邦查询场景。
Catalog实现
1 Flink Catalog
Flink Catalog的实现有两种:Hive Catalog和Memory Catalog。两者都继承抽象的AbstractCatalog,区别是前者借助HMS来管理元数据,后者基于内存管理,Flink Job停止之后,这些数据会丢失,需要重建。
2 Iceberg Catalog
Iceberg Catalog的实现类有4种,Hive Catalog、Hadoop Catalog、CacheCatalog和JDBC Catalog。它们都继承抽象类BaseMetastoreCatalog。Hive Catalog将表的元数据信息存储在Hive Metastore,为了兼容HMS,Namespace必须包含table和database。
Hadoop Catalog将表的元数据信息存储在Hadoop之上,因为Hadoop支持存算分离,因此底层的数据文件可以是HDFS或者是S3这样的对象系统,对Hadoop Catalog来讲,定位一个表的位置,只需要提供表的路径即可,因为表的元信息都存储在文件中,比如TableIdentifier为["test_table","test_db","test_nm1","test_nm2"]的表全路径为:
对Hadoop Catalog来讲,Namespace可以只有一层,即table 名称即可,它并不关心数据库的概念,只关心表的位置,但在实际应用中,为了规范管理表,建议使用规范的组织方式,具体如何组织,要看企业的行为习惯,目前没有最佳实践。
需要提醒一点的是,Hadoop Catalog构建在文件系统之上,一些文件系统不支持的操作,Catalog也无法实现,比如对表名的更改,涉及到更改路径,对象存储系统无法支持,有代码为证:
public class HadoopCatalog{
@Override
public void renameTable(TableIdentifier from, TableIdentifier to) {
throw new UnsupportedOperationException("Cannot rename Hadoop tables");
}
}
同Flink Catalog一样,Iceberg也提供了JDBC Catalog,JDBC Catalog将表的元信息存储在支持JDBC协议的数据库中。但是两者还是有区别的:Flink的JDBC Catalog能够查询注册和查询外部JDBC数据源,而Iceberg的JDBC Catalog只是将本身的元数据存储在JDBC数据库中,Iceberg目前支持的数据来源也仅仅是Hadoop。除了以上三类Catalog,Iceberg也提供了自定义Catalog实现,这类的典型实现是AWS Glue。CacheCatalog类似Flink的MemoryCatalog。
3 Hive Catalog
虽然Hive 没有跟Flink、Iceberg类似的Catalog相关接口定义,但是在IMetaStoreClient接口有相似的实现,而且更完善:
上面只是截取了部分接口定义,实际上还有很多,感兴趣的读者自己去翻阅IMetaStoreClient接口定义。
Catalog管理
从前面介绍可知,Flink和Iceberg分别实现了多种Catalog的实例,在实际使用当中,如何方便跟使用方交互呢?
1 Flink Catalog
Flink通过定义类CatalogManager来组织当前系统中可用的Catalog和设置、查询当前Catalog等的信息:
@Internal public final class CatalogManager {
// A map between names and catalogs.
private final Map catalogs;
// The name of the current catalog and database
private String currentCatalogName;
private String currentDatabaseName;
}
在Catalogmanager的外围,通过StreamTableEnvironment暴露给用户常用的操作接口,比如查询当前系统所有的Catalog,当前Catalog 的所有表和数据库等:
其中registerCatalog方法将Catalog实现注册到Catalogmanager,默认是MemoryCatalog。何为StreamTableEnvironment?文档中这么描述:
A table environment is responsible for:
- Connecting to external systems.
- Registering and retrieving Tables and other meta objects from a catalog.
- Executing SQL statements.
- Offering further configuration options.
StreamTableEnvironment的基本用法如下:
tableEnv.registerCatalog(catalogName, hiveCatalog);
tableEnv.useCatalog(catalogName);
tableEnv.executeSql("CREATE TABLE...");
tableEnv.executeSql会在注册的Catalog下创建数据表,如果没有指定Catalog和数据库,会在类型为GenericInMemoryCatalog,默认名为default_catalog 的默认default_db下创建表。比如下面的示例,在外部数据源mysql上创建了一张映射表,可以在Flink中对其进行读写操作:
-- register a MySQL table 'users' in Flink SQL
CREATE TABLE MyUserTable (
id BIGINT,
name STRING,
age INT,
status BOOLEAN,
PRIMARY KEY (id) NOT ENFORCED )
WITH ( 'connector' = 'jdbc', 'url' = 'jdbc:mysql://localhost:3306/mydatabase', 'table-name' = 'users' );
再比如下面,将Kafka指定的Topic user_behavior映射到Flink中的表KafkaTable,然后通过Flink对其进行读写:
CREATE TABLE KafkaTable (
event_time TIMESTAMP(3) METADATA FROM 'value.source.timestamp' VIRTUAL, -- from Debezium format
origin_table STRING METADATA FROM 'value.source.table' VIRTUAL, -- from Debezium format
partition_id BIGINT METADATA FROM 'partition' VIRTUAL, -- from Kafka connector
offset BIGINT METADATA VIRTUAL, -- from Kafka connector
user_id BIGINT,
item_id BIGINT,
behavior STRING )
WITH (
'connector' = 'kafka',
'topic' = 'user_behavior',
'properties.bootstrap.servers' = 'localhost:9092',
'properties.group.id' = 'testGroup',
'scan.startup.mode' = 'earliest-offset',
'value.format' = 'debezium-json'
);
Currently, PostgresCatalog is the only implementation of JDBC Catalog at the moment。如需使用,需要引入依赖:
org.apache.flink
flink-connector-jdbc_2.11
1.14.0
使用方式示例:
JdbcCatalog catalog = new JdbcCatalog(name, defaultDatabase, username, password, baseUrl);
tableEnv.registerCatalog("mypg", catalog);
// set the JdbcCatalog as the current catalog of the session tableEnv.useCatalog("mypg");
2 Iceberg Catalog
Iceberg Catalog的CatalogLoader等价于Catalog Mamager,接口中实现了3种CatalogLoader:hadoop、Hive和custom,见下图:
在对外接口暴露中,通过TableLoader:
" title="" src="http://img.e-com-net.com/image/info9/f7634fed020845bf9cd52b06f784f219.jpg" width="0" height="0">
一旦有了TableLoader,就可以通过去loadTable方法加载相应的表。上述接口可以通过API方便的调用,那如何通过SQL方式跟Iceberg交互呢?下面列举了Hive、Hadoop和Custom三种Catalog的用法:
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' );
CREATE CATALOG hadoop_catalog
WITH (
'type'='iceberg',
'catalog-type'='hadoop',
'warehouse'='hdfs://nn:8020/warehouse/path',
'property-version'='1' );
CREATE CATALOG my_catalog WITH (
'type'='iceberg',
'catalog-impl'='com.my.custom.CatalogImpl',
'my-additional-catalog-config'='my-value' );
有了Catalog就可以进行通常的ddl了,比如创建一张表sample:
CREATE TABLE hive_catalog.default.sample (
id BIGINT COMMENT 'unique id',
data STRING );
3 Hive Catalog
" title="" src="http://img.e-com-net.com/image/info9/29d6fc769f8947a192692eec19e538bf.jpg" width="0" height="0">
HiveMetaStoreClient、HiveMetaStoreClientPreCatalog、CacheableHiveMetaStoreClient和SessionHiveMetaStoreClient都是IMetaStoreClient接口类的实现,最常用的是HiveMetaStoreClient。在对外暴露接口方面,既可以使用HiveMetaStoreClient,也可以使用HCatalog。HCatalog是Hadoop的表存储管理工具,扩展了HiveMetaStoreClient的功能,它将Hive Metastore的表格数据公开给其他Hadoop应用程序,使得具有不同数据处理工具(Pig,MapReduce)的用户能够轻松将数据写入表格。它确保用户不必担心数据存储在何处或以何种格式存储。Hcatalog可以通过命令行及REST API来访问HiveMetaStore,允许你使用HiveQLDDL语法来定义表。
" title="" src="http://img.e-com-net.com/image/info9/c1e5618fba524e0fb98c88277ec3db48.jpg" width="0" height="0">
以下是HCatalog的三个基本用途:
- 工具间通信——大多数复杂的Hadoop应用程序都会使用多种工具来处理相同的数据。它们可能将Pig和MapReduce的组合用于抽取、转换、加载(ETL)的实现,MapReduce用于实际的数据处理,而Hive用于分析查询。中心化元数据存储库的使用简化了数据共享,并确保了某个工具的执行结果总是对其他工具可见。
- 数据发现——对于大型Hadoop集群来说,常见的情形是应用程序和数据具有多样性。通常,一个应用程序的数据可以被其他应用程序使用,但试图发现这些情况需要大量跨应用程序的信息。在这种情况下,可以将HCatalog用作对任何应用程序可见的注册表。将数据在HCatalog中发布就可以让其他应用程序发现它们。
- 系统集成——HCatalog所提供的REST服务,打开了Hadoop数据和处理的大门,使其可以应用在整体的企业级数据和处理基础设施中。Hadoop以简易API和类似SQL语言的形式提供了简单的接口。
小结
Flink和Iceberg都实现了相似的Catalog 管理功能,前者通过CatalogManager,后者通过CatalogLoader。两者相同点都支持HMS和JDBC,但是Iceberg也有额外对Hadoop的支持。Hive Catalog因为出现较早,没有专门的CatalogManager,但是它的 MetaStoreClient接口实现了同样的功能,而且更为完善。不仅如此,HCatalog的引入解决不同Hadoop应用之间,按照统一规范的方式访问HDFS文件数据。另外,HMS 底层存储支持derby、jdbc数据库等。相比而言,Flink和Iceberg是横向发展,而Hive是纵向发展。
生态扩展
在Catalog之上,Flinl、Iceberg和Hive通过不同的方式来拓展自己的生态。
1 Flink Catalog
Flink主要通过Connector来连接不同类型的Source和Sink,Source比如Kafka、Kinesis、RabbitMQ、ActiveMQ等,Sink比如Kafka、Kinesis、RabbitMQ、ActiveMQ、HDFS、Redis、Elasticsearch、Cassandra等,使用这些Connector,需要引入相应的依赖包,对于系统自带的比如Socket、Files、Collections、Std Out等可以直接使用,除了上述类型之外,为满足自定义使用场景,Flink还提供了SourceFunction和SinkFunction。完整的系统生态支持类型列举如下:
2 Iceberg Catalog
Iceberg实现了名叫FlinkCatalog的Catalog,该Catalog不同于Iceberg的Catalog,是Flink定义的类型。理论上,Fink Source支持的的数据源都可以写入Iceberg。因此Iceberg的生态拓展方式可以这样描述:
3 Hive Catalog
Hive没有类似Connector的概念,Hive是通过HiveStorageHandler接口来提供对不同数据格式的访问,下面是Hive已经实现的StorageHandler:
其中比较常用的是DefaultStorageHandler、HBaseStorageHandler、DruidStorageHandler和JdbcStorageHandler。DefaultStorageHandler常用于基类,用于实现自定义StoargeHandler,JdbcStorageHandler较新。
引入Storage Handler,Hive用户使用SQL可读写外部数据源。ElasticSearch, Kafka,HBase等数据源的查询对非专业开发是有一定门槛的,借助Storage Handler,他们有了一种方便快捷的手段查询数据。另外,Hive作为数仓的核心组件,借助Storage Handler,数据导入导出可以统一以SQL实现,减少了大数据开发维护的技术栈。下图列举了常用的一些Storage Handler实现:
小结
在生态拓展方面,Flink主要通过Connector机制支持不同数据源和数据目的的读取和写入;Iceberg则借助Flink的Source Connector能力,向下支持基于Hadoop的数据入湖,间接方式来拓展生态边界;Hive通过HiveStorageHandler接口,外部通过实现HiveStorageHandler来接入对不同数据源的支持。在积极性方面,Flink处于积极进攻态势,Iceberg处于练内功阶段,Hive正在补短板,处于积极追赶态势。
总结
Catalog是大数据技术体系中至关重要的一环,本文从技术角度,从Catalog 的接口定义、Catalog的实现、Cataslog的管理和生态拓展几个方面比较了Flink、Iceberg和Hive在这方面的应用和发展,研究结果表明Flink、Iceberg和Hive都具备了一定的Catalog管理方面的能力,但是发展节奏不同:Flink在流计算方面发展较快,并且建立起了相对完善的生态,Iceberg处于后到一方,目前专注于湖上数据的组织管理,在数据获取方面通过拥抱Flink大腿来拓展生态边界,而Hive属于传统离线数据的元数据管理的绝对霸主,相对Flink等计算引擎,Hive向内发展,在纵向拓展方面发展很完善,在横向发展方面,目前处于查漏补缺,积极追赶阶段,比如实现了Streaming处理,在联邦查询方面,通过外部三方系统的支持,也拓展到了HBase、Kafka、Iceberg、JDBC等技术体系。而且Hive Metastore也被Flink、Iceberg深度依赖,看起来相当长时间都很难摆脱对HMS的依赖(也没有摆脱的必要),但是Hive还不具备对JDBC Catalog等自动元数据发现能力,因此如果需要开发新的Catalog Manager,较好的方式依然是像Flink、Iceberg做的那样,将HMS集成到系统之中,然后再横向拓展其他类型的Catalog。
参考链接
https://www.oracle.com/big-da...
https://iceberg.apache.org/#h...
https://nightlies.apache.org/...
https://trino.io/docs/current...
https://issues.apache.org/jir...
0505-使用Apache Hive3实现跨数据库的联邦查询