支持高吞吐数据摄入、变更追踪、高效分析的流批数据湖
基于LSM提升写入速度并降低写入消耗;基于有序的SortRun裁剪大部分数据以提升查询性能;支持多种merge引擎实现高性能流表打宽
特点
是 Flink SQL 的内置存储
- Flink DDL 会真实创建或删除物理表,不再只是一个外部物理表的映射
- 掩盖和抽象底层技术细节,没有烦人的选项如connector配置
支持亚秒级流写入和消费
高吞吐量扫描能力
降低了认知门槛,存储需要自动处理各种Insert/Update/Delete输入和表定义
- 接收任何类型的变更日志,接收任何类型的数据类型
- 表可以有主键或没有主键
支持多种引擎
存储
LogStore append延时很低,但有TTL限制,可用于流读。FileStore确保可以查询历史数据:
- LogStore:存储最新数据,支持秒级流式增量消费,默认使用Kafka实现
- 完全支持插入/更新/删除
- 根据主键(若有)或整行(无主键)将记录散列到不同的kafka分区
- FileStore:存储最新数据+历史数据,提供批量Ad-Hoc分析,使用LSM、parquet/orc实现
- 为了完全支持插入/更新/删除和可选的主键定义,我们需要一个支持更新和自定义合并的灵活存储结构,LSM 是一个不错的选择
- 为了支持高性能和多场景分析,应该支持多种列式文件格式
- key若有主键则默认json格式,若无则空。value默认使用debezium-json格式
如果是流模式且开启change-tracking,log与file同时生效,生成HybridSource读,如果是流模式且未开启change-tracking、批模式,生成FileStoreSource读。
文件结构
元数据与数据存储在表的同一级目录下,包括 snapshot 目录、manifest 目录、schema 目录、数据文件。桶文件是读写的最小存储单元。
每个snapshot会有对应的一个base清单列表、一个delta清单列表文件,base清单列表包含了本次操作之前的清单文件,清单列表文件会对应一个或多个清单,每个清单会对应一个或多个不同操作类型的数据文件
- snapshot 目录:记录了每次提交产生的 snapshot 文件,记录了本次 commit 正在使用的schema文件、新增了哪些 manifest 文件、删除了哪些 manifest 文件
- snapshot-x 一次checkpoint生成一个或两个snapshot(当有append、compact同时发生时出现会生成两个),若检查点间隔内未写入数据,只会创建compact快照
- EARLIEST 最早的快照编号,一开始是-8
- LATEST 最新的快照编号
- manifest 目录:记录了每次经 checkpoint 触发而提交的数据文件变更,每个文件记录了产生了哪些 sst 文件、删除了哪些 sst 文件,以及每个 sst 文件所包含记录的主键范围、每个字段的 min/max/null count 等统计信息
- schema 目录:表结构文件
- 数据文件:按分区、存储桶分到对应目录,每个桶目录都包含一个LSM树和变更日志文件,每个 sst 文件则包含了按主键排好序的、列存格式的记录。对于 Level 0 的文件,会异步地触发 compact 合并线程来消除主键范围重叠带来的读端 merge 开销
- LSM树将sst文件组织成多个SortedRun,SortedRun与文件是一对多的关系,对于主键表,不同的SortedRun可能具有重叠的主键范围或相同的主键,查询LSM树时必须MOR,根据指定的合并引擎和每条记录的时间戳来合并所有SortedRun
- 当write-buffer-size耗尽时会将数据flush生成文件
基于Flink&Paimon实现,提供数据一致性管理能力,解决流式数仓普遍存在的问题
paimon通过snapshot定义数据版本,即数据按snapshot对齐。
流式数仓普遍存在的问题:
- 缺少血缘管理(表血缘、数据血缘)
- 缺少统一的版本管理(多表关联查询时不一致)
- 数据订正困难(复杂的数据修正过程、链路双跑、业务逻辑修正)
实现方案:提交阶段查询系统表中的血缘表设置起始消费位置;运行阶段按照消费的snapshot粒度响应chkpt请求,chkpt coordinator将barrier放在两个snapshot中间;chkpt成功后通知sink提交对应的表;提交完成后由CommitListener将血缘关系写入系统表
Catalog
- file
CREATE CATALOG my_catalog WITH ( 'type' = 'paimon', 'warehouse' = 'hdfs:///path/to/warehouse' ); USE CATALOG my_catalog;
- hive
表
分类
- 管理表,paimon catalog下建的表,删除会删所有数据
- 外部表,非paimon catalog下建的表,属性要有'connector'='paimon', 'path'='xxx',可以直接读写外部的paimon数据,删除后只是show tables无,未删元数据、数据
- 临时表,仅flink支持,在paimon catalog下建的外部表,会话级的,会话退出后自动失效。create tempoary table t1,with属性与外部表一样
- 系统表,表名$系统表名,如快照表$snapshots、schema表$schemas、选项表$options、审计日志表$audit_log、文件表$files
有主键表
如果定义具有主键的表,则可以在表中插入、更新或删除记录。
无主键表
1、append表
若无主键则默认是append表。流式传输只能向表中插入一条完整的记录。这种类型的表适合不需要流式更新的用例。默认是zstd压缩
CREATE TABLE my_table ( product_id BIGINT, price DOUBLE, sales BIGINT ) WITH ( 'file.compression' = 'zstd' );
流式读取:
- 默认情况下,流式读取在第一次启动时会对表生成最新的快照,并继续读取最新的增量记录。
- 可以指定scan.mode、scan.snapshot-id、scan.timestamp-millis或scan.file-creation-time-millis仅流式读取增量。
OLAP查询
- 按顺序跳过数据,Paimon 默认记录清单文件中每个字段的最大值和最小值,在查询的时候,根据WHERE查询的条件,根据manifest中的统计信息做文件过滤
- 按文件索引跳过数据
CREATE TABLE <PAIMON_TABLE> (<COLUMN> <COLUMN_TYPE> , ...) WITH ( 'file-index.bloom-filter.columns' = 'c1,c2', 'file-index.bloom-filter.c1.items' = '200' );
2、bucketed append表
必须指定bucket-key
CREATE TABLE my_table ( product_id BIGINT, price DOUBLE, sales BIGINT ) WITH ( 'bucket' = '8', &#