流式数据湖Paimon探秘之旅 (三) Catalog体系深度解析

第3章:Catalog体系深度解析

总览:什么是Catalog?

Catalog 是Paimon的元数据管理中心,负责统一管理所有数据库、表及其Schema信息。

可以把Catalog想象成一个"图书馆管理系统":

  • Catalog = 图书馆本身
  • Database = 图书馆的各个楼层/区域
  • Table = 图书的具体书名
  • Schema = 书的目录结构(章节、页数等)

Catalog核心设计

3.1 Catalog接口设计

核心功能分类

Catalog提供以下核心功能:

java 复制代码
Catalog接口 {
  // 数据库操作
  createDatabase(name, properties)
  dropDatabase(name, cascade)
  listDatabases()
  getDatabase(name)
  alterDatabase(name, changes)
  
  // 表操作
  createTable(identifier, schema)
  dropTable(identifier)
  getTable(identifier)
  listTables(databaseName)
  alterTable(identifier, schemaChanges)
  
  // Schema管理
  getSchema(identifier) -> TableSchema
  
  // 版本管理(如果支持)
  createTag(identifier, tag, snapshot)
  deleteTag(identifier, tag)
  rollbackTo(identifier, instant)
  
  // 分布式锁
  lockFactory() -> Optional<LockFactory>
  
  // 文件系统
  fileIO() -> FileIO
}
多种实现

Paimon提供了多种Catalog实现:

实现 元数据存储 特点 适用场景
FileSystemCatalog 文件系统(HDFS/S3等) 简单、独立、无外部依赖 数据湖、BI系统
HiveCatalog Hive Metastore 与Hive生态兼容 Hive用户、数据仓库
JdbcCatalog 数据库(MySQL/PG) 高可用、支持事务 生产环境、对可用性要求高
RESTCatalog 远程REST服务 集中管理、多集群共享 多租户、云原生
CachingCatalog 其他Catalog + 本地缓存 性能优化 频繁访问元数据

3.2 FileSystemCatalog实现原理

什么(What):FileSystemCatalog如何存储元数据?

FileSystemCatalog将所有元数据存储在文件系统上:

bash 复制代码
warehouse/
└── db_name/                    # 数据库目录
    ├── .paimon/               # Paimon系统目录
    │   └── database           # 数据库配置文件
    └── table_name/
        ├── .paimon/
        │   ├── schema/
        │   │   └── schema-0.json  # Schema版本
        │   └── options            # 表选项
        └── data/                  # 数据目录
为什么(Why):为什么选择文件系统?
优点 具体体现
无外部依赖 无需部署Hive、Postgres等
高可用 元数据就是数据,与数据一起备份
云友好 支持HDFS、S3、OSS等所有云存储
成本低 利用现有存储基础设施
易于调试 可以直接查看JSON文件
怎样(How):实现细节

创建数据库:

java 复制代码
catalog.createDatabase("mydb", ignoreIfExists=true);

执行步骤:
1. 检查warehouse/mydb/.paimon/database是否存在
2. 如果不存在,写入文件:
   warehouse/mydb/.paimon/database (包含数据库名称)
3. 检查完成

创建表:

java 复制代码
Schema schema = new Schema(
    fields(...),
    primaryKeys("id"),
    options({"bucket": "4"})
);
catalog.createTable(
    Identifier.create("mydb", "users"),
    schema
);

执行步骤:
1. 创建表目录:warehouse/mydb/users/
2. 写入Schema文件:warehouse/mydb/users/.paimon/schema/schema-0.json
3. 写入选项文件:warehouse/mydb/users/.paimon/options
4. 初始化数据目录

读取表元数据:

java 复制代码
Table table = catalog.getTable(Identifier.create("mydb", "users"));

执行步骤:
1. 读取schema-0.json → 获得表结构
2. 读取options文件 → 获得表配置
3. 创建FileStoreTable实例 → 用户可见

3.3 元数据管理与Schema演化

什么是Schema演化(Schema Evolution)?

Schema演化是指在不丢失现有数据的前提下,修改表结构的能力。

例如:

sql 复制代码
-- 初始表
CREATE TABLE users (id INT, name VARCHAR(50));

-- 添加新列
ALTER TABLE users ADD COLUMN age INT;

-- 删除列
ALTER TABLE users DROP COLUMN name;

-- 重命名列
ALTER TABLE users RENAME COLUMN age TO user_age;
Paimon如何支持Schema演化?

核心原理:版本化Schema

bash 复制代码
时刻1:schema-0.json
{
  "fields": [
    {"id": 0, "name": "id", "type": "INT"},
    {"id": 1, "name": "name", "type": "VARCHAR(50)"}
  ]
}
↓ 添加age列
时刻2:schema-1.json
{
  "fields": [
    {"id": 0, "name": "id", "type": "INT"},
    {"id": 1, "name": "name", "type": "VARCHAR(50)"},
    {"id": 2, "name": "age", "type": "INT"}
  ]
}
↓ 删除name列
时刻3:schema-2.json
{
  "fields": [
    {"id": 0, "name": "id", "type": "INT"},
    {"id": 2, "name": "age", "type": "INT"}
  ]
}

特点:
- 每次Schema修改都生成新版本
- 列的ID(id字段)永不改变
- 旧数据继续使用旧Schema,新数据使用新Schema
- 读取时自动适配不同版本的数据

读取过程:

kotlin 复制代码
查询:"SELECT id, age FROM users WHERE id=1"

执行:
1. 扫描Manifest,找到data-file-1(使用schema-0)和data-file-2(使用schema-2)
2. 读data-file-1时:schema-0没有age列 → 填充NULL
3. 读data-file-2时:schema-2有age列 → 正常读取
4. 合并结果:
   (id=1, age=NULL)  from data-file-1
   (id=1, age=25)    from data-file-2
常见Schema演化操作

操作1:添加列

java 复制代码
List<SchemaChange> changes = new ArrayList<>();
changes.add(SchemaChange.addColumn("age", DataTypes.INT()));
catalog.alterTable(
    Identifier.create("db", "users"),
    changes
);

效果:
- 新数据包含age列
- 旧数据的age值为NULL

操作2:删除列

java 复制代码
List<SchemaChange> changes = new ArrayList<>();
changes.add(SchemaChange.dropColumn("age"));
catalog.alterTable(
    Identifier.create("db", "users"),
    changes
);

效果:
- 新数据不含age列
- 旧数据忽略age列

操作3:修改列类型

java 复制代码
List<SchemaChange> changes = new ArrayList<>();
changes.add(SchemaChange.updateColumnType(
    "age",
    DataTypes.BIGINT()  // INT → BIGINT
));

注意:
- 需要确保类型兼容(可自动转换)
- 不支持不兼容的转换(如STRING → INT)

3.4 CachingCatalog缓存优化

为什么需要缓存?

在高频查询场景下,频繁读取文件系统元数据会成为瓶颈:

sql 复制代码
查询1:SELECT * FROM users WHERE id=1
  → 读取Schema
  → 读取FileStore配置
  → 执行查询
  
查询2:SELECT * FROM users WHERE id=2
  → 再次读取Schema (重复!)
  → 再次读取FileStore配置 (重复!)
  → 执行查询

CachingCatalog的作用:缓存频繁访问的元数据

scss 复制代码
┌──────────────────────────┐
│   CachingCatalog         │
│  ┌────────────────────┐  │
│  │   本地缓存(内存)    │  │
│  │  schema, filestore │  │
│  └────────┬───────────┘  │
│           ↓               │
│  ┌────────────────────┐  │
│  │ 下层Catalog实现    │  │
│  │(FileSystem/Hive)   │  │
│  └────────────────────┘  │
└──────────────────────────┘
缓存策略

时间驱动缓存:

java 复制代码
Options options = new Options();
options.set(CacheOption.ENABLE, true);
options.set(CacheOption.EXPIRE_AFTER_WRITE, Duration.ofMinutes(10));

Catalog catalog = CatalogFactory.createCatalog(options);

效果:
- 缓存在内存中最多保留10分钟
- 10分钟后自动过期,重新从底层读取

大小驱动缓存:

java 复制代码
options.set(CacheOption.CACHE_SIZE, "100MB");

效果:
- 当缓存大小超过100MB时,淘汰最近未使用的条目
- 使用LRU算法

手动失效:

java 复制代码
// 更新Table后,需要主动清除缓存
catalog.alterTable(identifier, schemaChanges);
((CachingCatalog)catalog).invalidateCache();  // 清除所有缓存

或针对性清除:
((CachingCatalog)catalog).invalidateTable(identifier);  // 清除特定表的缓存

总结:Catalog的核心价值

1. 统一的元数据视图

scss 复制代码
Flink用户
  ↓
Catalog(统一元数据入口)
  ↓
┌─────────────┬─────────────┬──────────────┐
Spark用户   Hive用户    Python用户

2. 灵活的后端实现

scss 复制代码
应用代码只依赖Catalog接口
       ↓
具体实现可以灵活替换
FileSystemCatalog → HiveCatalog
  (开发环境)       (生产环境)

3. Schema演化支持

sql 复制代码
业务需求变化
  ↓
表结构调整(ALTER TABLE)
  ↓
现有数据 + 新数据 无缝兼容

4. 性能优化

复制代码
CachingCatalog + 本地缓存
  ↓
元数据访问延迟 降低 10-100倍
  ↓
查询响应时间显著提升

相关推荐
语落心生1 小时前
流式数据湖Paimon探秘之旅 (六) 提交流程与事务保证
大数据
梦里不知身是客111 小时前
容量调度器
大数据
跨境海外仓小秋1 小时前
仓库如何实现自动汇总订单波次?TOPWMS波次规则助力海外仓拣货效率翻倍
大数据
民乐团扒谱机1 小时前
【微实验】携程评论C#爬取实战:突破JavaScript动态加载与反爬虫机制
大数据·开发语言·javascript·爬虫·c#
涤生大数据1 小时前
Spark分桶表实战:如何用分桶减少 40%+ 计算时间
大数据·sql·spark·分桶表·大数据校招·大数据八股
武子康1 小时前
大数据-170 Elasticsearch 7.3.0 三节点集群实战:目录/参数/启动到联机
大数据·后端·elasticsearch
G皮T2 小时前
【Elasticsearch】索引状态管理(ISM)实战(万字长文)
大数据·elasticsearch·搜索引擎·ilm·ism·索引状态管理·索引生命周期管理
豪越大豪2 小时前
消防智能装备全生命周期管理 —— 告别 “台账 + 库存 + 维护” 多系统!
大数据
2401_861277552 小时前
HPCC,Cloudera,Cassandra,Storm是什么工具
大数据