一、概述

Spark 中的 DataSet 和 Dateframe API 支持结构化分析。结构化分析的一个重要的方面是管理元数据。这些元数据可能是一些临时元数据(比如临时表)SQLContext 上注册的 UDF 以及持久化的元数据。

Spark 的早期版本并没有标准的 API 來访问这些元数据的。用户通常使用查询语句(比如 show tables) 来查询这些元数据。这些查询通常需要操作原始的字符串,而且不同元数据类型的操作也是不一样的。
Spark 2.0 中添加了标准的 API(称为 Catalog) 来访问 Spark SQL 中的元数据。

二、设计

2.1. Spark 2.x 的 Catalog 体系

2.1.1. 设计

在 Spark 2.× 中,Spark SQL 中的 Catalog 体系实现以 SessionCatalog 为主体,通过 SparkSession 提供给外部调用。

一般一个 SparkSession 对应—个 SessionCatalog,本质上,SessionCatalog 起到了一个代理的作用,对底层的元数据信息、临时表信息!视图信息和函数信息进行了封装。

SessionCatalog 的构造参数包括 6 部分,除传入 SparkSQL 和 Hadoop 配置信息的 CatalystConf 与 Configuration 外,还涉及以下4个方面的内容。

  1. GlobalTempViewManager(全局的临时视图管理)
    对应 DataFrame 中常用的 createGlobalTempView() 方法,进行跨 Session 的视图管理。GlobalTempViewManager 是一个线程安全的类.提供了对全局视图的原子操作、包括创建、更新、刪除和重命名等。

    在 GlobalTempViewManager 内部实现中,主要功能依赖一个 mutable 类型的 HashMap 来对视图名和数据源进行映射,其中的 key 是视图名的字符串,value 是视图所对应的 LogicalPlan(一般在创建该视图时生成)。

    1
    private val viewDefinitions = new mutable.HashMap[String, TemporaryViewRelation]

    需要注意的是,GlobalTempViewManager 对视图名是大小写敏感的。

  2. FunctionResourceLoader(函数资源加载器)
    在 Spark SQL 中除内置实现的各种函数外,还支持用户自定义的函数和 Hive 中的各种函数。

  3. FunctionRegistry(函数注册接口)
    用来实现对函数的注册(Register)、查找(Lookup)和删除(Drop) 等功能。一般来讲,FunctionRegistry 的具体实现需要是线程安金的,以支持并发访问。在 Spark SQL 中默认实现是 SimpleFunctionRegistry,其中采用 Map 数据结构注册了各种内置的函数。

  4. ExternalCatalog (外部系统Catalog)

    用来管理数据库(Databases)数据表(Tables)、数据分区(Partitions)和函数(Functions)的接口。其目标是与外部系统交互,并做到上述内容的非临时性存储,同样需要满足线程安全以支持并发访问。在 Spark SQL中,具体实现有 InMemoryCatalog 和 HiveExternalCatalog 两种。

2.1.2. 不足

2.2. Spark 3.X 的 Catalog 体系

随着新数据源 DataSourceV2 的出现,原来的 SessionCatalog 暴露出弊端和不足,为了适应新的数据源特性,Spark 推出了新的接口: CatalogPlugin。

2.2.1. 设计

2.2.2. 自定义 Catalog

DelegatingCatalogExtension 是Spark 中的一个扩展,它可以用来自定义 Spark 的元数据管理。这个扩展可以用来支持不同的元数据存储系统,这个扩展的核心理念是将元数据的管理委托给其他系统,这样可以方便的进行元数据的维护和更换。